From 5c6cef5ac868a8470b86468bcdfd3a86f9fc1e7f Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Sun, 14 Dec 2014 20:24:48 +0100 Subject: [PATCH] Added patches for CSMT support (not enabled yet). --- README.md | 3 +- patches/Makefile | 385 + ...01-wined3d-Merge-get_pitch-functions.patch | 406 + patches/wined3d-CSMT_Helper/definition | 0 ...ass-a-context-to-surface_load_sysmem.patch | 79 + ...s-a-context-to-read_from_framebuffer.patch | 81 + ...ontext-to-surface_load_drawable-and-.patch | 121 + ...3d-Pass-a-context-to-surface_blt_fbo.patch | 140 + ...ontext-to-surface_multisample_resolv.patch | 49 + ...ss-a-context-to-surface_load_texture.patch | 100 + ...s-a-context-to-surface_load_location.patch | 543 + ...surface_load_location-return-nothing.patch | 106 + ...ore-volume-locations-in-the-resource.patch | 203 + ...Move-validate_location-to-resource.c.patch | 116 + ...-surface-locations-into-the-resource.patch | 457 + ...d3d-Remove-surface_validate_location.patch | 217 + ...ve-invalidate_location-to-resource.c.patch | 161 + ...d-Invalidate-containers-via-callback.patch | 144 + ...d-Remove-surface_invalidate_location.patch | 327 + ...map_data-and-user_memory-into-the-re.patch | 171 + ...Move-load_location-into-the-resource.patch | 309 + ...surface_load_location-with-resource_.patch | 411 + ...e-helper-functions-for-mapping-volum.patch | 213 + ...ume-PBO-infrastructure-into-the-reso.patch | 311 + .../0021-wined3d-Remove-surface-pbo.patch | 160 + ...urce-buffer-mapping-facilities-in-su.patch | 177 + ...ve-buffer-creation-into-the-resource.patch | 278 + ...INED3D_LOCATION_DISCARDED-in-surface.patch | 31 + ...OCATION_DISCARDED-in-surface_load_dr.patch | 29 + ...INED3D_LOCATION_DISCARDED-for-sysmem.patch | 75 + ...-Discard-implicit-surfaces-on-unload.patch | 36 + ...y-to-flip-sysmem-copies-in-swapchain.patch | 73 + ...d-the-backbuffer-in-discard-presents.patch | 43 + ...-sysmem-for-client-storage-if-it-doe.patch | 37 + ...e-a-function-to-retrieve-resource-me.patch | 159 + ...face_ops-unmap-specific-for-front-bu.patch | 116 + ...Move-check_block_align-to-resource.c.patch | 152 + ...surface-alloc-functions-with-resourc.patch | 230 + ...delete-the-buffer-in-surface_cleanup.patch | 29 + ...-resource-facilities-to-destroy-PBOs.patch | 81 + ...ple-location-copying-to-the-resource.patch | 158 + ...ove-most-of-volume_map-to-resource.c.patch | 294 + ...d3d-Use-resource_map-for-surface_map.patch | 196 + ...Use-client-storage-with-DIB-sections.patch | 78 + ...ll-the-public-map-function-in-surfac.patch | 101 + ...ll-the-public-map-function-in-surfac.patch | 292 + ...e-the-framebuffer-into-wined3d_state.patch | 932 ++ ...of-state-access-in-shader_generate_g.patch | 63 + ...ad-buffers-if-streamsrc-is-not-dirty.patch | 65 + ...introduce-a-multithreaded-command-st.patch | 867 ++ ...-resource-updates-to-finish-when-usi.patch | 190 + ...ore-pointers-in-struct-wined3d_cs_pr.patch | 82 + ...t-rectangle-pointers-into-wined3d_cs.patch | 76 + ...e-color-in-clear-ops-instead-of-a-po.patch | 43 + ...d3d-Pass-the-state-to-draw_primitive.patch | 258 + ...for-the-cs-before-destroying-objects.patch | 135 + ...53-wined3d-Give-the-cs-its-own-state.patch | 255 + ...at-constant-updates-through-the-comm.patch | 208 + ...a-glFinish-before-modifying-resource.patch | 253 + ...he-cs-before-changing-the-texture-lo.patch | 30 + ...d3d-Don-t-call-glFinish-after-clears.patch | 27 + ...ed3d-Don-t-call-glFinish-after-draws.patch | 27 + ...evice-offscreenBuffer-in-the-context.patch | 54 + ...cess-the-stateblock-in-find_draw_buf.patch | 105 + ...e-depth-stencil-to-swapchain-present.patch | 95 + ...ore-viewport-pointers-in-the-command.patch | 47 + ...ck-of-the-onscreen-depth-stencil-in-.patch | 216 + ...e-vertex-index-updates-through-the-c.patch | 178 + ...mitive-type-updates-through-the-comm.patch | 151 + ...l-constant-updates-through-the-comma.patch | 192 + ...-constant-updates-through-the-comman.patch | 175 + ...ht-updates-through-the-command-strea.patch | 394 + ...the-command-stream-from-running-ahea.patch | 60 + ...-the-cs-to-finish-before-destroying-.patch | 26 + ...71-wined3d-Run-the-cs-asynchronously.patch | 25 + ...end-blits-through-the-command-stream.patch | 555 + ...-update_surface-checks-back-in-place.patch | 125 + ...ed3d-Get-rid-of-WINED3D_BUFFER_FLUSH.patch | 57 + ...75-wined3d-Add-cs-waiting-debug-code.patch | 29 + ...rce-strict-draw-ordering-for-multith.patch | 26 + ...der-target-view-clears-through-the-c.patch | 118 + ...078-wined3d-Wait-for-the-CS-in-GetDC.patch | 37 + ...ource-maps-through-the-command-strea.patch | 273 + ...id-of-the-end_scene-flush-and-finish.patch | 45 + ...e-the-linked-lists-with-a-ringbuffer.patch | 843 ++ ...ned3d-Don-t-preload-buffers-on-unmap.patch | 27 + ...-Don-t-call-glFinish-before-swapping.patch | 29 + ...3d-wined3d_-_query_issue-never-fails.patch | 116 + ...-query-support-to-the-command-stream.patch | 163 + ...r-CS-state-to-find-out-if-a-query-is.patch | 72 + ...Poll-queries-automatically-in-the-CS.patch | 586 + ...e-a-separate-queue-for-priority-comm.patch | 268 + ...ned3d-Destroy-queries-through-the-CS.patch | 183 + ...e-main-and-worker-thread-query-state.patch | 138 + ...-t-poll-queries-that-failed-to-start.patch | 134 + ...-restated-queries-from-the-poll-list.patch | 40 + ...set-the-query-state-if-it-doesn-t-ha.patch | 31 + ...d-Put-this-into-the-query-poll-patch.patch | 52 + ...date_surface-commands-through-the-CS.patch | 128 + ...Send-texture-preloads-through-the-CS.patch | 107 + ...Send-surface-preloads-through-the-CS.patch | 112 + ...-update_texture-calls-through-the-CS.patch | 310 + ...-of-the-surface_upload_data-glFinish.patch | 27 + ...ck-the-src-volume-in-device_update_v.patch | 50 + ...vit_managed_resources-through-the-CS.patch | 129 + ...end-flips-through-the-command-stream.patch | 115 + ...3-wined3d-Introduce-resource-fencing.patch | 99 + ...date_texture-and-update_surface-call.patch | 117 + ...5-wined3d-Dirtify-resources-on-unmap.patch | 81 + ...wined3d-Fence-texture-reads-in-draws.patch | 53 + ...ce-render-targets-and-depth-stencils.patch | 75 + .../0108-wined3d-Fence-blit-operations.patch | 38 + ...-wined3d-Fence-color_fill-operations.patch | 34 + .../0110-wined3d-Fence-clear-calls.patch | 72 + .../0111-wined3d-Fence-present-calls.patch | 54 + ...ource-maps-and-unmaps-a-priority-com.patch | 80 + ...changed-textures-through-the-command.patch | 176 + ...4-wined3d-Wrap-GL-BOs-in-a-structure.patch | 269 + ...parate-resource-map-and-draw-buffers.patch | 69 + ...t-DISCARD-resource-maps-with-buffers.patch | 150 + ...t-DISCARD-resource-maps-with-heap-me.patch | 258 + ...t-some-objects-in-state_init_default.patch | 34 + ...quest-the-frontbuffer-to-create-dumm.patch | 26 + ...le-buffered-buffers-for-multithreade.patch | 26 + ...-synchronize-NOOVERWRITE-buffer-maps.patch | 58 + ...-buffer-map-write-and-draw-read-memo.patch | 47 + ...ned3d-Accelerate-DISCARD-buffer-maps.patch | 139 + ...ed3d-Accelerate-READONLY-buffer-maps.patch | 29 + ...he-buffer-dirty-areas-through-the-CS.patch | 140 + ...-buffer-resource.map_count-in-the-CS.patch | 58 + ...-Send-buffer-preloads-through-the-CS.patch | 122 + ...fferSubData-instead-of-glMapBufferRa.patch | 91 + ...-GL-buffer-discard-control-from-igno.patch | 135 + ...d-Create-buffers-before-mapping-them.patch | 66 + ...wined3d-Destroy-views-through-the-CS.patch | 173 + ...0132-wined3d-Remove-another-glFinish.patch | 28 + ...y-vertex-declarations-through-the-CS.patch | 131 + ...ned3d-Destroy-shaders-through-the-CS.patch | 126 + ...eate-VBOs-through-the-command-stream.patch | 133 + ...lean-up-resource-data-through-the-CS.patch | 211 + ...-buffer-resource-data-through-the-CS.patch | 156 + ...-volume-resource-data-through-the-CS.patch | 122 + ...d3d-Clean-up-surfaces-through-the-cs.patch | 178 + ...-up-texture-resources-through-the-cs.patch | 291 + ...esources-through-the-CS-in-uninit_3d.patch | 29 + ...esources-through-the-CS-in-device_re.patch | 44 + ...t-glFinish-after-a-depth-buffer-blit.patch | 27 + ...ned3d-Remove-software-cursor-support.patch | 190 + ...Create-dummy-textures-through-the-CS.patch | 157 + ...e-the-initial-context-through-the-CS.patch | 240 + ...-ctx-and-dummy-textures-through-the-.patch | 62 + ...INED3D_MAP_NO_DIRTY_UPDATE-in-resour.patch | 37 + ...-GL-contexts-through-the-CS-in-reset.patch | 147 + ...L-contexts-through-the-CS-in-uninit_.patch | 79 + ...urface_unload-through-the-CS-in-wine.patch | 31 + ...vent-to-block-the-worker-thread-when.patch | 177 + ...153-wined3d-Fence-preload-operations.patch | 89 + ...CK_NO_DIRTY_UPDATE-on-managed-textur.patch | 26 + ...CK_NO_DIRTY_UPDATE-on-managed-textur.patch | 26 + ...-Completely-reset-the-state-on-reset.patch | 24 + ...dc-and-releasedc-through-the-command.patch | 274 + ...heap_memory-NULL-when-allocating-a-P.patch | 31 + ...-Wait-only-for-the-buffer-to-be-idle.patch | 27 + ...dd-a-comment-about-worker-thread-lag.patch | 31 + ...-Remove-the-texture-destroy-glFinish.patch | 32 + ...O-destruction-into-the-worker-thread.patch | 40 + ...cref-decref-textures-in-color-depth-.patch | 134 + ...0164-Winex11-complain-about-glfinish.patch | 32 + ...e-the-new-window-is-set-up-before-se.patch | 69 + ...emove-the-device_reset-CS-sync-fixme.patch | 32 + ...PPLE_flush_buffer_range-syncing-back.patch | 52 + ...-the-resource-to-be-idle-when-destro.patch | 41 + ...on-t-sync-on-redundant-discard-calls.patch | 25 + ...70-wined3d-Don-t-discard-new-buffers.patch | 24 + ...y-to-sync-VBOs-manually-on-OSX-with-.patch | 52 + ...0172-wined3d-Render-target-lock-hack.patch | 86 + ...lling-wined3d_surface_blt-from-surfa.patch | 42 + ...x-some-uninitialized-memory-accesses.patch | 47 + ...SMT-by-default-print-a-winediag-mess.patch | 50 + .../wined3d-CSMT_Main/9999-IfDefined.patch | 9662 +++++++++++++++++ patches/wined3d-CSMT_Main/definition | 3 + 181 files changed, 34347 insertions(+), 1 deletion(-) create mode 100644 patches/wined3d-CSMT_Helper/0001-wined3d-Merge-get_pitch-functions.patch create mode 100644 patches/wined3d-CSMT_Helper/definition create mode 100644 patches/wined3d-CSMT_Main/0001-wined3d-Pass-a-context-to-surface_load_sysmem.patch create mode 100644 patches/wined3d-CSMT_Main/0002-wined3d-Pass-a-context-to-read_from_framebuffer.patch create mode 100644 patches/wined3d-CSMT_Main/0003-wined3d-Pass-a-context-to-surface_load_drawable-and-.patch create mode 100644 patches/wined3d-CSMT_Main/0004-wined3d-Pass-a-context-to-surface_blt_fbo.patch create mode 100644 patches/wined3d-CSMT_Main/0005-wined3d-Pass-a-context-to-surface_multisample_resolv.patch create mode 100644 patches/wined3d-CSMT_Main/0006-wined3d-Pass-a-context-to-surface_load_texture.patch create mode 100644 patches/wined3d-CSMT_Main/0007-wined3d-Pass-a-context-to-surface_load_location.patch create mode 100644 patches/wined3d-CSMT_Main/0008-wined3d-Make-surface_load_location-return-nothing.patch create mode 100644 patches/wined3d-CSMT_Main/0009-wined3d-Store-volume-locations-in-the-resource.patch create mode 100644 patches/wined3d-CSMT_Main/0010-wined3d-Move-validate_location-to-resource.c.patch create mode 100644 patches/wined3d-CSMT_Main/0011-wined3d-Move-surface-locations-into-the-resource.patch create mode 100644 patches/wined3d-CSMT_Main/0012-wined3d-Remove-surface_validate_location.patch create mode 100644 patches/wined3d-CSMT_Main/0013-wined3d-Move-invalidate_location-to-resource.c.patch create mode 100644 patches/wined3d-CSMT_Main/0014-wined3d-Invalidate-containers-via-callback.patch create mode 100644 patches/wined3d-CSMT_Main/0015-wined3d-Remove-surface_invalidate_location.patch create mode 100644 patches/wined3d-CSMT_Main/0016-wined3d-Move-bitmap_data-and-user_memory-into-the-re.patch create mode 100644 patches/wined3d-CSMT_Main/0017-wined3d-Move-load_location-into-the-resource.patch create mode 100644 patches/wined3d-CSMT_Main/0018-wined3d-Replace-surface_load_location-with-resource_.patch create mode 100644 patches/wined3d-CSMT_Main/0019-wined3d-Introduce-helper-functions-for-mapping-volum.patch create mode 100644 patches/wined3d-CSMT_Main/0020-wined3d-Move-volume-PBO-infrastructure-into-the-reso.patch create mode 100644 patches/wined3d-CSMT_Main/0021-wined3d-Remove-surface-pbo.patch create mode 100644 patches/wined3d-CSMT_Main/0022-wined3d-Use-resource-buffer-mapping-facilities-in-su.patch create mode 100644 patches/wined3d-CSMT_Main/0023-wined3d-Move-buffer-creation-into-the-resource.patch create mode 100644 patches/wined3d-CSMT_Main/0024-wined3d-Handle-WINED3D_LOCATION_DISCARDED-in-surface.patch create mode 100644 patches/wined3d-CSMT_Main/0025-wined3d-Handle-LOCATION_DISCARDED-in-surface_load_dr.patch create mode 100644 patches/wined3d-CSMT_Main/0026-wined3d-Handle-WINED3D_LOCATION_DISCARDED-for-sysmem.patch create mode 100644 patches/wined3d-CSMT_Main/0027-wined3d-Discard-implicit-surfaces-on-unload.patch create mode 100644 patches/wined3d-CSMT_Main/0028-wined3d-Don-t-try-to-flip-sysmem-copies-in-swapchain.patch create mode 100644 patches/wined3d-CSMT_Main/0029-wined3d-Discard-the-backbuffer-in-discard-presents.patch create mode 100644 patches/wined3d-CSMT_Main/0030-wined3d-Allocate-sysmem-for-client-storage-if-it-doe.patch create mode 100644 patches/wined3d-CSMT_Main/0031-wined3d-Introduce-a-function-to-retrieve-resource-me.patch create mode 100644 patches/wined3d-CSMT_Main/0032-wined3d-Make-surface_ops-unmap-specific-for-front-bu.patch create mode 100644 patches/wined3d-CSMT_Main/0033-wined3d-Move-check_block_align-to-resource.c.patch create mode 100644 patches/wined3d-CSMT_Main/0034-wined3d-Replace-surface-alloc-functions-with-resourc.patch create mode 100644 patches/wined3d-CSMT_Main/0035-wined3d-Don-t-delete-the-buffer-in-surface_cleanup.patch create mode 100644 patches/wined3d-CSMT_Main/0036-wined3d-Use-resource-facilities-to-destroy-PBOs.patch create mode 100644 patches/wined3d-CSMT_Main/0037-wined3d-Move-simple-location-copying-to-the-resource.patch create mode 100644 patches/wined3d-CSMT_Main/0038-wined3d-Move-most-of-volume_map-to-resource.c.patch create mode 100644 patches/wined3d-CSMT_Main/0039-wined3d-Use-resource_map-for-surface_map.patch create mode 100644 patches/wined3d-CSMT_Main/0040-wined3d-Use-client-storage-with-DIB-sections.patch create mode 100644 patches/wined3d-CSMT_Main/0041-wined3d-Don-t-call-the-public-map-function-in-surfac.patch create mode 100644 patches/wined3d-CSMT_Main/0042-wined3d-Don-t-call-the-public-map-function-in-surfac.patch create mode 100644 patches/wined3d-CSMT_Main/0043-wined3d-Move-the-framebuffer-into-wined3d_state.patch create mode 100644 patches/wined3d-CSMT_Main/0044-wined3d-Get-rid-of-state-access-in-shader_generate_g.patch create mode 100644 patches/wined3d-CSMT_Main/0045-wined3d-Preload-buffers-if-streamsrc-is-not-dirty.patch create mode 100644 patches/wined3d-CSMT_Main/0046-wined3d-Hackily-introduce-a-multithreaded-command-st.patch create mode 100644 patches/wined3d-CSMT_Main/0047-wined3d-Wait-for-resource-updates-to-finish-when-usi.patch create mode 100644 patches/wined3d-CSMT_Main/0048-wined3d-Don-t-store-pointers-in-struct-wined3d_cs_pr.patch create mode 100644 patches/wined3d-CSMT_Main/0049-wined3d-Don-t-put-rectangle-pointers-into-wined3d_cs.patch create mode 100644 patches/wined3d-CSMT_Main/0050-wined3d-Store-the-color-in-clear-ops-instead-of-a-po.patch create mode 100644 patches/wined3d-CSMT_Main/0051-wined3d-Pass-the-state-to-draw_primitive.patch create mode 100644 patches/wined3d-CSMT_Main/0052-wined3d-Wait-for-the-cs-before-destroying-objects.patch create mode 100644 patches/wined3d-CSMT_Main/0053-wined3d-Give-the-cs-its-own-state.patch create mode 100644 patches/wined3d-CSMT_Main/0054-wined3d-Send-float-constant-updates-through-the-comm.patch create mode 100644 patches/wined3d-CSMT_Main/0055-wined3d-Request-a-glFinish-before-modifying-resource.patch create mode 100644 patches/wined3d-CSMT_Main/0056-wined3d-Finish-the-cs-before-changing-the-texture-lo.patch create mode 100644 patches/wined3d-CSMT_Main/0057-wined3d-Don-t-call-glFinish-after-clears.patch create mode 100644 patches/wined3d-CSMT_Main/0058-wined3d-Don-t-call-glFinish-after-draws.patch create mode 100644 patches/wined3d-CSMT_Main/0059-wined3d-Shadow-device-offscreenBuffer-in-the-context.patch create mode 100644 patches/wined3d-CSMT_Main/0060-wined3d-Don-t-access-the-stateblock-in-find_draw_buf.patch create mode 100644 patches/wined3d-CSMT_Main/0061-wined3d-Pass-the-depth-stencil-to-swapchain-present.patch create mode 100644 patches/wined3d-CSMT_Main/0062-wined3d-Don-t-store-viewport-pointers-in-the-command.patch create mode 100644 patches/wined3d-CSMT_Main/0063-wined3d-Keep-track-of-the-onscreen-depth-stencil-in-.patch create mode 100644 patches/wined3d-CSMT_Main/0064-wined3d-Send-base-vertex-index-updates-through-the-c.patch create mode 100644 patches/wined3d-CSMT_Main/0065-wined3d-Send-primitive-type-updates-through-the-comm.patch create mode 100644 patches/wined3d-CSMT_Main/0066-wined3d-Send-bool-constant-updates-through-the-comma.patch create mode 100644 patches/wined3d-CSMT_Main/0067-wined3d-Send-int-constant-updates-through-the-comman.patch create mode 100644 patches/wined3d-CSMT_Main/0068-wined3d-Send-light-updates-through-the-command-strea.patch create mode 100644 patches/wined3d-CSMT_Main/0069-wined3d-Prevent-the-command-stream-from-running-ahea.patch create mode 100644 patches/wined3d-CSMT_Main/0070-wined3d-Wait-for-the-cs-to-finish-before-destroying-.patch create mode 100644 patches/wined3d-CSMT_Main/0071-wined3d-Run-the-cs-asynchronously.patch create mode 100644 patches/wined3d-CSMT_Main/0072-wined3d-Send-blits-through-the-command-stream.patch create mode 100644 patches/wined3d-CSMT_Main/0073-wined3d-Put-update_surface-checks-back-in-place.patch create mode 100644 patches/wined3d-CSMT_Main/0074-wined3d-Get-rid-of-WINED3D_BUFFER_FLUSH.patch create mode 100644 patches/wined3d-CSMT_Main/0075-wined3d-Add-cs-waiting-debug-code.patch create mode 100644 patches/wined3d-CSMT_Main/0076-wined3d-Don-t-force-strict-draw-ordering-for-multith.patch create mode 100644 patches/wined3d-CSMT_Main/0077-wined3d-Send-render-target-view-clears-through-the-c.patch create mode 100644 patches/wined3d-CSMT_Main/0078-wined3d-Wait-for-the-CS-in-GetDC.patch create mode 100644 patches/wined3d-CSMT_Main/0079-wined3d-send-resource-maps-through-the-command-strea.patch create mode 100644 patches/wined3d-CSMT_Main/0080-wined3d-Get-rid-of-the-end_scene-flush-and-finish.patch create mode 100644 patches/wined3d-CSMT_Main/0081-wined3d-Replace-the-linked-lists-with-a-ringbuffer.patch create mode 100644 patches/wined3d-CSMT_Main/0082-wined3d-Don-t-preload-buffers-on-unmap.patch create mode 100644 patches/wined3d-CSMT_Main/0083-wined3d-Don-t-call-glFinish-before-swapping.patch create mode 100644 patches/wined3d-CSMT_Main/0084-wined3d-wined3d_-_query_issue-never-fails.patch create mode 100644 patches/wined3d-CSMT_Main/0085-wined3d-Add-query-support-to-the-command-stream.patch create mode 100644 patches/wined3d-CSMT_Main/0086-wined3d-Check-our-CS-state-to-find-out-if-a-query-is.patch create mode 100644 patches/wined3d-CSMT_Main/0087-wined3d-Poll-queries-automatically-in-the-CS.patch create mode 100644 patches/wined3d-CSMT_Main/0088-wined3d-Introduce-a-separate-queue-for-priority-comm.patch create mode 100644 patches/wined3d-CSMT_Main/0089-wined3d-Destroy-queries-through-the-CS.patch create mode 100644 patches/wined3d-CSMT_Main/0090-wined3d-Separate-main-and-worker-thread-query-state.patch create mode 100644 patches/wined3d-CSMT_Main/0091-wined3d-Don-t-poll-queries-that-failed-to-start.patch create mode 100644 patches/wined3d-CSMT_Main/0092-wined3d-Remove-restated-queries-from-the-poll-list.patch create mode 100644 patches/wined3d-CSMT_Main/0093-wined3d-Don-t-reset-the-query-state-if-it-doesn-t-ha.patch create mode 100644 patches/wined3d-CSMT_Main/0094-wined3d-Put-this-into-the-query-poll-patch.patch create mode 100644 patches/wined3d-CSMT_Main/0095-wined3d-Send-update_surface-commands-through-the-CS.patch create mode 100644 patches/wined3d-CSMT_Main/0096-wined3d-Send-texture-preloads-through-the-CS.patch create mode 100644 patches/wined3d-CSMT_Main/0097-wined3d-Send-surface-preloads-through-the-CS.patch create mode 100644 patches/wined3d-CSMT_Main/0098-wined3d-Send-update_texture-calls-through-the-CS.patch create mode 100644 patches/wined3d-CSMT_Main/0099-wined3d-Get-rid-of-the-surface_upload_data-glFinish.patch create mode 100644 patches/wined3d-CSMT_Main/0100-wined3d-Don-t-lock-the-src-volume-in-device_update_v.patch create mode 100644 patches/wined3d-CSMT_Main/0101-wined3d-Handle-evit_managed_resources-through-the-CS.patch create mode 100644 patches/wined3d-CSMT_Main/0102-wined3d-Send-flips-through-the-command-stream.patch create mode 100644 patches/wined3d-CSMT_Main/0103-wined3d-Introduce-resource-fencing.patch create mode 100644 patches/wined3d-CSMT_Main/0104-wined3d-Fence-update_texture-and-update_surface-call.patch create mode 100644 patches/wined3d-CSMT_Main/0105-wined3d-Dirtify-resources-on-unmap.patch create mode 100644 patches/wined3d-CSMT_Main/0106-wined3d-Fence-texture-reads-in-draws.patch create mode 100644 patches/wined3d-CSMT_Main/0107-wined3d-Fence-render-targets-and-depth-stencils.patch create mode 100644 patches/wined3d-CSMT_Main/0108-wined3d-Fence-blit-operations.patch create mode 100644 patches/wined3d-CSMT_Main/0109-wined3d-Fence-color_fill-operations.patch create mode 100644 patches/wined3d-CSMT_Main/0110-wined3d-Fence-clear-calls.patch create mode 100644 patches/wined3d-CSMT_Main/0111-wined3d-Fence-present-calls.patch create mode 100644 patches/wined3d-CSMT_Main/0112-wined3d-Make-resource-maps-and-unmaps-a-priority-com.patch create mode 100644 patches/wined3d-CSMT_Main/0113-wined3d-Dirtify-changed-textures-through-the-command.patch create mode 100644 patches/wined3d-CSMT_Main/0114-wined3d-Wrap-GL-BOs-in-a-structure.patch create mode 100644 patches/wined3d-CSMT_Main/0115-wined3d-Separate-resource-map-and-draw-buffers.patch create mode 100644 patches/wined3d-CSMT_Main/0116-wined3d-Implement-DISCARD-resource-maps-with-buffers.patch create mode 100644 patches/wined3d-CSMT_Main/0117-wined3d-Implement-DISCARD-resource-maps-with-heap-me.patch create mode 100644 patches/wined3d-CSMT_Main/0118-wined3d-Unset-some-objects-in-state_init_default.patch create mode 100644 patches/wined3d-CSMT_Main/0119-wined3d-Don-t-request-the-frontbuffer-to-create-dumm.patch create mode 100644 patches/wined3d-CSMT_Main/0120-wined3d-Use-double-buffered-buffers-for-multithreade.patch create mode 100644 patches/wined3d-CSMT_Main/0121-wined3d-Don-t-synchronize-NOOVERWRITE-buffer-maps.patch create mode 100644 patches/wined3d-CSMT_Main/0122-wined3d-Separate-buffer-map-write-and-draw-read-memo.patch create mode 100644 patches/wined3d-CSMT_Main/0123-wined3d-Accelerate-DISCARD-buffer-maps.patch create mode 100644 patches/wined3d-CSMT_Main/0124-wined3d-Accelerate-READONLY-buffer-maps.patch create mode 100644 patches/wined3d-CSMT_Main/0125-wined3d-Access-the-buffer-dirty-areas-through-the-CS.patch create mode 100644 patches/wined3d-CSMT_Main/0126-wined3d-Ignore-buffer-resource.map_count-in-the-CS.patch create mode 100644 patches/wined3d-CSMT_Main/0127-wined3d-Send-buffer-preloads-through-the-CS.patch create mode 100644 patches/wined3d-CSMT_Main/0128-wined3d-Use-glBufferSubData-instead-of-glMapBufferRa.patch create mode 100644 patches/wined3d-CSMT_Main/0129-wined3d-Separate-GL-buffer-discard-control-from-igno.patch create mode 100644 patches/wined3d-CSMT_Main/0130-wined3d-Create-buffers-before-mapping-them.patch create mode 100644 patches/wined3d-CSMT_Main/0131-wined3d-Destroy-views-through-the-CS.patch create mode 100644 patches/wined3d-CSMT_Main/0132-wined3d-Remove-another-glFinish.patch create mode 100644 patches/wined3d-CSMT_Main/0133-wined3d-Destroy-vertex-declarations-through-the-CS.patch create mode 100644 patches/wined3d-CSMT_Main/0134-wined3d-Destroy-shaders-through-the-CS.patch create mode 100644 patches/wined3d-CSMT_Main/0135-wined3d-Create-VBOs-through-the-command-stream.patch create mode 100644 patches/wined3d-CSMT_Main/0136-wined3d-Clean-up-resource-data-through-the-CS.patch create mode 100644 patches/wined3d-CSMT_Main/0137-wined3d-Clean-up-buffer-resource-data-through-the-CS.patch create mode 100644 patches/wined3d-CSMT_Main/0138-wined3d-Clean-up-volume-resource-data-through-the-CS.patch create mode 100644 patches/wined3d-CSMT_Main/0139-wined3d-Clean-up-surfaces-through-the-cs.patch create mode 100644 patches/wined3d-CSMT_Main/0140-wined3d-Clean-up-texture-resources-through-the-cs.patch create mode 100644 patches/wined3d-CSMT_Main/0141-wined3d-Unload-resources-through-the-CS-in-uninit_3d.patch create mode 100644 patches/wined3d-CSMT_Main/0142-wined3d-Unload-resources-through-the-CS-in-device_re.patch create mode 100644 patches/wined3d-CSMT_Main/0143-wined3d-Don-t-glFinish-after-a-depth-buffer-blit.patch create mode 100644 patches/wined3d-CSMT_Main/0144-wined3d-Remove-software-cursor-support.patch create mode 100644 patches/wined3d-CSMT_Main/0145-wined3d-Create-dummy-textures-through-the-CS.patch create mode 100644 patches/wined3d-CSMT_Main/0146-wined3d-Create-the-initial-context-through-the-CS.patch create mode 100644 patches/wined3d-CSMT_Main/0147-wined3d-Recreate-ctx-and-dummy-textures-through-the-.patch create mode 100644 patches/wined3d-CSMT_Main/0148-wined3d-Ignore-WINED3D_MAP_NO_DIRTY_UPDATE-in-resour.patch create mode 100644 patches/wined3d-CSMT_Main/0149-wined3d-Delete-GL-contexts-through-the-CS-in-reset.patch create mode 100644 patches/wined3d-CSMT_Main/0150-wined3d-Delete-GL-contexts-through-the-CS-in-uninit_.patch create mode 100644 patches/wined3d-CSMT_Main/0151-wined3d-Invoke-surface_unload-through-the-CS-in-wine.patch create mode 100644 patches/wined3d-CSMT_Main/0152-wined3d-Use-an-event-to-block-the-worker-thread-when.patch create mode 100644 patches/wined3d-CSMT_Main/0153-wined3d-Fence-preload-operations.patch create mode 100644 patches/wined3d-CSMT_Main/0154-d3d8-tests-D3DLOCK_NO_DIRTY_UPDATE-on-managed-textur.patch create mode 100644 patches/wined3d-CSMT_Main/0155-d3d9-tests-D3DLOCK_NO_DIRTY_UPDATE-on-managed-textur.patch create mode 100644 patches/wined3d-CSMT_Main/0156-wined3d-Completely-reset-the-state-on-reset.patch create mode 100644 patches/wined3d-CSMT_Main/0157-wined3d-Send-getdc-and-releasedc-through-the-command.patch create mode 100644 patches/wined3d-CSMT_Main/0158-wined3d-Set-map_heap_memory-NULL-when-allocating-a-P.patch create mode 100644 patches/wined3d-CSMT_Main/0159-wined3d-Wait-only-for-the-buffer-to-be-idle.patch create mode 100644 patches/wined3d-CSMT_Main/0160-wined3d-Add-a-comment-about-worker-thread-lag.patch create mode 100644 patches/wined3d-CSMT_Main/0161-wined3d-Remove-the-texture-destroy-glFinish.patch create mode 100644 patches/wined3d-CSMT_Main/0162-wined3d-Move-FBO-destruction-into-the-worker-thread.patch create mode 100644 patches/wined3d-CSMT_Main/0163-wined3d-Don-t-incref-decref-textures-in-color-depth-.patch create mode 100644 patches/wined3d-CSMT_Main/0164-Winex11-complain-about-glfinish.patch create mode 100644 patches/wined3d-CSMT_Main/0165-wined3d-Make-sure-the-new-window-is-set-up-before-se.patch create mode 100644 patches/wined3d-CSMT_Main/0166-wined3d-Remove-the-device_reset-CS-sync-fixme.patch create mode 100644 patches/wined3d-CSMT_Main/0167-wined3d-Put-GL_APPLE_flush_buffer_range-syncing-back.patch create mode 100644 patches/wined3d-CSMT_Main/0168-wined3d-Wait-for-the-resource-to-be-idle-when-destro.patch create mode 100644 patches/wined3d-CSMT_Main/0169-wined3d-Don-t-sync-on-redundant-discard-calls.patch create mode 100644 patches/wined3d-CSMT_Main/0170-wined3d-Don-t-discard-new-buffers.patch create mode 100644 patches/wined3d-CSMT_Main/0171-wined3d-Don-t-try-to-sync-VBOs-manually-on-OSX-with-.patch create mode 100644 patches/wined3d-CSMT_Main/0172-wined3d-Render-target-lock-hack.patch create mode 100644 patches/wined3d-CSMT_Main/0173-wined3d-Avoid-calling-wined3d_surface_blt-from-surfa.patch create mode 100644 patches/wined3d-CSMT_Main/0174-wined3d-Fix-some-uninitialized-memory-accesses.patch create mode 100644 patches/wined3d-CSMT_Main/0175-wined3d-Enable-CSMT-by-default-print-a-winediag-mess.patch create mode 100644 patches/wined3d-CSMT_Main/9999-IfDefined.patch create mode 100644 patches/wined3d-CSMT_Main/definition diff --git a/README.md b/README.md index 986647cf..075de2af 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Wine. All those differences are also documented on the Included bug fixes and improvements =================================== -**Bugfixes and features included in the next upcoming release [13]:** +**Bugfixes and features included in the next upcoming release [14]:** * Add support for GetPropValue to PulseAudio backend * Fix condition mask handling in RtlVerifyVersionInfo ([Wine Bug #36143](https://bugs.winehq.org/show_bug.cgi?id=36143)) @@ -48,6 +48,7 @@ Included bug fixes and improvements * Provide named entry point shell32.SHILCreateFromPath for vista apps ([Wine Bug #37265](https://bugs.winehq.org/show_bug.cgi?id=37265)) * Reallocate buffer when adding records to AVI files ([Wine Bug #5137](https://bugs.winehq.org/show_bug.cgi?id=5137)) * Set last error when GetRawInputDeviceList fails ([Wine Bug #37667](https://bugs.winehq.org/show_bug.cgi?id=37667)) +* Support for CSMT (command stream) to increase graphic performance ([Wine Bug #11674](https://bugs.winehq.org/show_bug.cgi?id=11674)) * Support for StrCatChainW * Support for combase HSTRING objects * Support for loader dll redirections diff --git a/patches/Makefile b/patches/Makefile index e027e184..b3813668 100644 --- a/patches/Makefile +++ b/patches/Makefile @@ -119,6 +119,8 @@ PATCHLIST := \ wine.inf-ProductId.ok \ wineboot-HKEY_DYN_DATA.ok \ winebuild-LinkerVersion.ok \ + wined3d-CSMT_Helper.ok \ + wined3d-CSMT_Main.ok \ wined3d-DXTn.ok \ wined3d-Revert_PixelFormat.ok \ winedevice-Fix_Relocation.ok \ @@ -1840,6 +1842,389 @@ winebuild-LinkerVersion.ok: echo '+ { "Michael Müller", "winebuild: Set a valid major and minor linker version.", 1 },'; \ ) > winebuild-LinkerVersion.ok +# Patchset wined3d-CSMT_Helper +# | +# | Modified files: +# | * dlls/ddraw/surface.c, dlls/wined3d/resource.c, dlls/wined3d/surface.c, dlls/wined3d/volume.c, dlls/wined3d/wined3d.spec, +# | dlls/wined3d/wined3d_private.h, include/wine/wined3d.h +# | +.INTERMEDIATE: wined3d-CSMT_Helper.ok +wined3d-CSMT_Helper.ok: + $(call APPLY_FILE,wined3d-CSMT_Helper/0001-wined3d-Merge-get_pitch-functions.patch) + @( \ + echo '+ { "Stefan Dösinger", "wined3d: Merge get_pitch functions.", 1 },'; \ + ) > wined3d-CSMT_Helper.ok + +# Patchset wined3d-CSMT_Main +# | +# | This patchset fixes the following Wine bugs: +# | * [#11674] Support for CSMT (command stream) to increase graphic performance +# | +# | Modified files: +# | * dlls/d3d8/tests/visual.c, dlls/d3d9/tests/visual.c, dlls/wined3d/arb_program_shader.c, dlls/wined3d/buffer.c, +# | dlls/wined3d/context.c, dlls/wined3d/cs.c, dlls/wined3d/device.c, dlls/wined3d/directx.c, dlls/wined3d/drawprim.c, +# | dlls/wined3d/glsl_shader.c, dlls/wined3d/query.c, dlls/wined3d/resource.c, dlls/wined3d/shader.c, dlls/wined3d/state.c, +# | dlls/wined3d/stateblock.c, dlls/wined3d/surface.c, dlls/wined3d/swapchain.c, dlls/wined3d/texture.c, +# | dlls/wined3d/utils.c, dlls/wined3d/vertexdeclaration.c, dlls/wined3d/view.c, dlls/wined3d/volume.c, +# | dlls/wined3d/wined3d_main.c, dlls/wined3d/wined3d_private.h, dlls/winex11.drv/opengl.c +# | +.INTERMEDIATE: wined3d-CSMT_Main.ok +wined3d-CSMT_Main.ok: wined3d-CSMT_Helper.ok + $(call APPLY_FILE,wined3d-CSMT_Main/0001-wined3d-Pass-a-context-to-surface_load_sysmem.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0002-wined3d-Pass-a-context-to-read_from_framebuffer.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0003-wined3d-Pass-a-context-to-surface_load_drawable-and-.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0004-wined3d-Pass-a-context-to-surface_blt_fbo.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0005-wined3d-Pass-a-context-to-surface_multisample_resolv.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0006-wined3d-Pass-a-context-to-surface_load_texture.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0007-wined3d-Pass-a-context-to-surface_load_location.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0008-wined3d-Make-surface_load_location-return-nothing.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0009-wined3d-Store-volume-locations-in-the-resource.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0010-wined3d-Move-validate_location-to-resource.c.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0011-wined3d-Move-surface-locations-into-the-resource.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0012-wined3d-Remove-surface_validate_location.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0013-wined3d-Move-invalidate_location-to-resource.c.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0014-wined3d-Invalidate-containers-via-callback.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0015-wined3d-Remove-surface_invalidate_location.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0016-wined3d-Move-bitmap_data-and-user_memory-into-the-re.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0017-wined3d-Move-load_location-into-the-resource.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0018-wined3d-Replace-surface_load_location-with-resource_.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0019-wined3d-Introduce-helper-functions-for-mapping-volum.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0020-wined3d-Move-volume-PBO-infrastructure-into-the-reso.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0021-wined3d-Remove-surface-pbo.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0022-wined3d-Use-resource-buffer-mapping-facilities-in-su.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0023-wined3d-Move-buffer-creation-into-the-resource.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0024-wined3d-Handle-WINED3D_LOCATION_DISCARDED-in-surface.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0025-wined3d-Handle-LOCATION_DISCARDED-in-surface_load_dr.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0026-wined3d-Handle-WINED3D_LOCATION_DISCARDED-for-sysmem.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0027-wined3d-Discard-implicit-surfaces-on-unload.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0028-wined3d-Don-t-try-to-flip-sysmem-copies-in-swapchain.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0029-wined3d-Discard-the-backbuffer-in-discard-presents.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0030-wined3d-Allocate-sysmem-for-client-storage-if-it-doe.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0031-wined3d-Introduce-a-function-to-retrieve-resource-me.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0032-wined3d-Make-surface_ops-unmap-specific-for-front-bu.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0033-wined3d-Move-check_block_align-to-resource.c.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0034-wined3d-Replace-surface-alloc-functions-with-resourc.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0035-wined3d-Don-t-delete-the-buffer-in-surface_cleanup.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0036-wined3d-Use-resource-facilities-to-destroy-PBOs.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0037-wined3d-Move-simple-location-copying-to-the-resource.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0038-wined3d-Move-most-of-volume_map-to-resource.c.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0039-wined3d-Use-resource_map-for-surface_map.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0040-wined3d-Use-client-storage-with-DIB-sections.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0041-wined3d-Don-t-call-the-public-map-function-in-surfac.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0042-wined3d-Don-t-call-the-public-map-function-in-surfac.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0043-wined3d-Move-the-framebuffer-into-wined3d_state.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0044-wined3d-Get-rid-of-state-access-in-shader_generate_g.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0045-wined3d-Preload-buffers-if-streamsrc-is-not-dirty.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0046-wined3d-Hackily-introduce-a-multithreaded-command-st.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0047-wined3d-Wait-for-resource-updates-to-finish-when-usi.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0048-wined3d-Don-t-store-pointers-in-struct-wined3d_cs_pr.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0049-wined3d-Don-t-put-rectangle-pointers-into-wined3d_cs.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0050-wined3d-Store-the-color-in-clear-ops-instead-of-a-po.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0051-wined3d-Pass-the-state-to-draw_primitive.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0052-wined3d-Wait-for-the-cs-before-destroying-objects.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0053-wined3d-Give-the-cs-its-own-state.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0054-wined3d-Send-float-constant-updates-through-the-comm.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0055-wined3d-Request-a-glFinish-before-modifying-resource.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0056-wined3d-Finish-the-cs-before-changing-the-texture-lo.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0057-wined3d-Don-t-call-glFinish-after-clears.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0058-wined3d-Don-t-call-glFinish-after-draws.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0059-wined3d-Shadow-device-offscreenBuffer-in-the-context.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0060-wined3d-Don-t-access-the-stateblock-in-find_draw_buf.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0061-wined3d-Pass-the-depth-stencil-to-swapchain-present.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0062-wined3d-Don-t-store-viewport-pointers-in-the-command.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0063-wined3d-Keep-track-of-the-onscreen-depth-stencil-in-.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0064-wined3d-Send-base-vertex-index-updates-through-the-c.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0065-wined3d-Send-primitive-type-updates-through-the-comm.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0066-wined3d-Send-bool-constant-updates-through-the-comma.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0067-wined3d-Send-int-constant-updates-through-the-comman.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0068-wined3d-Send-light-updates-through-the-command-strea.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0069-wined3d-Prevent-the-command-stream-from-running-ahea.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0070-wined3d-Wait-for-the-cs-to-finish-before-destroying-.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0071-wined3d-Run-the-cs-asynchronously.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0072-wined3d-Send-blits-through-the-command-stream.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0073-wined3d-Put-update_surface-checks-back-in-place.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0074-wined3d-Get-rid-of-WINED3D_BUFFER_FLUSH.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0075-wined3d-Add-cs-waiting-debug-code.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0076-wined3d-Don-t-force-strict-draw-ordering-for-multith.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0077-wined3d-Send-render-target-view-clears-through-the-c.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0078-wined3d-Wait-for-the-CS-in-GetDC.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0079-wined3d-send-resource-maps-through-the-command-strea.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0080-wined3d-Get-rid-of-the-end_scene-flush-and-finish.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0081-wined3d-Replace-the-linked-lists-with-a-ringbuffer.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0082-wined3d-Don-t-preload-buffers-on-unmap.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0083-wined3d-Don-t-call-glFinish-before-swapping.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0084-wined3d-wined3d_-_query_issue-never-fails.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0085-wined3d-Add-query-support-to-the-command-stream.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0086-wined3d-Check-our-CS-state-to-find-out-if-a-query-is.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0087-wined3d-Poll-queries-automatically-in-the-CS.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0088-wined3d-Introduce-a-separate-queue-for-priority-comm.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0089-wined3d-Destroy-queries-through-the-CS.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0090-wined3d-Separate-main-and-worker-thread-query-state.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0091-wined3d-Don-t-poll-queries-that-failed-to-start.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0092-wined3d-Remove-restated-queries-from-the-poll-list.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0093-wined3d-Don-t-reset-the-query-state-if-it-doesn-t-ha.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0094-wined3d-Put-this-into-the-query-poll-patch.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0095-wined3d-Send-update_surface-commands-through-the-CS.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0096-wined3d-Send-texture-preloads-through-the-CS.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0097-wined3d-Send-surface-preloads-through-the-CS.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0098-wined3d-Send-update_texture-calls-through-the-CS.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0099-wined3d-Get-rid-of-the-surface_upload_data-glFinish.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0100-wined3d-Don-t-lock-the-src-volume-in-device_update_v.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0101-wined3d-Handle-evit_managed_resources-through-the-CS.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0102-wined3d-Send-flips-through-the-command-stream.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0103-wined3d-Introduce-resource-fencing.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0104-wined3d-Fence-update_texture-and-update_surface-call.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0105-wined3d-Dirtify-resources-on-unmap.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0106-wined3d-Fence-texture-reads-in-draws.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0107-wined3d-Fence-render-targets-and-depth-stencils.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0108-wined3d-Fence-blit-operations.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0109-wined3d-Fence-color_fill-operations.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0110-wined3d-Fence-clear-calls.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0111-wined3d-Fence-present-calls.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0112-wined3d-Make-resource-maps-and-unmaps-a-priority-com.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0113-wined3d-Dirtify-changed-textures-through-the-command.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0114-wined3d-Wrap-GL-BOs-in-a-structure.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0115-wined3d-Separate-resource-map-and-draw-buffers.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0116-wined3d-Implement-DISCARD-resource-maps-with-buffers.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0117-wined3d-Implement-DISCARD-resource-maps-with-heap-me.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0118-wined3d-Unset-some-objects-in-state_init_default.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0119-wined3d-Don-t-request-the-frontbuffer-to-create-dumm.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0120-wined3d-Use-double-buffered-buffers-for-multithreade.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0121-wined3d-Don-t-synchronize-NOOVERWRITE-buffer-maps.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0122-wined3d-Separate-buffer-map-write-and-draw-read-memo.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0123-wined3d-Accelerate-DISCARD-buffer-maps.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0124-wined3d-Accelerate-READONLY-buffer-maps.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0125-wined3d-Access-the-buffer-dirty-areas-through-the-CS.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0126-wined3d-Ignore-buffer-resource.map_count-in-the-CS.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0127-wined3d-Send-buffer-preloads-through-the-CS.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0128-wined3d-Use-glBufferSubData-instead-of-glMapBufferRa.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0129-wined3d-Separate-GL-buffer-discard-control-from-igno.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0130-wined3d-Create-buffers-before-mapping-them.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0131-wined3d-Destroy-views-through-the-CS.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0132-wined3d-Remove-another-glFinish.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0133-wined3d-Destroy-vertex-declarations-through-the-CS.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0134-wined3d-Destroy-shaders-through-the-CS.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0135-wined3d-Create-VBOs-through-the-command-stream.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0136-wined3d-Clean-up-resource-data-through-the-CS.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0137-wined3d-Clean-up-buffer-resource-data-through-the-CS.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0138-wined3d-Clean-up-volume-resource-data-through-the-CS.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0139-wined3d-Clean-up-surfaces-through-the-cs.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0140-wined3d-Clean-up-texture-resources-through-the-cs.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0141-wined3d-Unload-resources-through-the-CS-in-uninit_3d.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0142-wined3d-Unload-resources-through-the-CS-in-device_re.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0143-wined3d-Don-t-glFinish-after-a-depth-buffer-blit.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0144-wined3d-Remove-software-cursor-support.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0145-wined3d-Create-dummy-textures-through-the-CS.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0146-wined3d-Create-the-initial-context-through-the-CS.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0147-wined3d-Recreate-ctx-and-dummy-textures-through-the-.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0148-wined3d-Ignore-WINED3D_MAP_NO_DIRTY_UPDATE-in-resour.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0149-wined3d-Delete-GL-contexts-through-the-CS-in-reset.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0150-wined3d-Delete-GL-contexts-through-the-CS-in-uninit_.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0151-wined3d-Invoke-surface_unload-through-the-CS-in-wine.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0152-wined3d-Use-an-event-to-block-the-worker-thread-when.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0153-wined3d-Fence-preload-operations.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0154-d3d8-tests-D3DLOCK_NO_DIRTY_UPDATE-on-managed-textur.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0155-d3d9-tests-D3DLOCK_NO_DIRTY_UPDATE-on-managed-textur.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0156-wined3d-Completely-reset-the-state-on-reset.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0157-wined3d-Send-getdc-and-releasedc-through-the-command.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0158-wined3d-Set-map_heap_memory-NULL-when-allocating-a-P.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0159-wined3d-Wait-only-for-the-buffer-to-be-idle.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0160-wined3d-Add-a-comment-about-worker-thread-lag.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0161-wined3d-Remove-the-texture-destroy-glFinish.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0162-wined3d-Move-FBO-destruction-into-the-worker-thread.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0163-wined3d-Don-t-incref-decref-textures-in-color-depth-.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0164-Winex11-complain-about-glfinish.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0165-wined3d-Make-sure-the-new-window-is-set-up-before-se.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0166-wined3d-Remove-the-device_reset-CS-sync-fixme.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0167-wined3d-Put-GL_APPLE_flush_buffer_range-syncing-back.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0168-wined3d-Wait-for-the-resource-to-be-idle-when-destro.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0169-wined3d-Don-t-sync-on-redundant-discard-calls.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0170-wined3d-Don-t-discard-new-buffers.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0171-wined3d-Don-t-try-to-sync-VBOs-manually-on-OSX-with-.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0172-wined3d-Render-target-lock-hack.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0173-wined3d-Avoid-calling-wined3d_surface_blt-from-surfa.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0174-wined3d-Fix-some-uninitialized-memory-accesses.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/0175-wined3d-Enable-CSMT-by-default-print-a-winediag-mess.patch) + $(call APPLY_FILE,wined3d-CSMT_Main/9999-IfDefined.patch) + @( \ + echo '+ { "Stefan Dösinger", "wined3d: Pass a context to surface_load_sysmem.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Pass a context to read_from_framebuffer.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Pass a context to surface_load_drawable and surface_blt_to_drawable.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Pass a context to surface_blt_fbo.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Pass a context to surface_multisample_resolve.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Pass a context to surface_load_texture.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Pass a context to surface_load_location.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Make surface_load_location return nothing.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Store volume locations in the resource.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Move validate_location to resource.c.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Move surface locations into the resource.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Remove surface_validate_location.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Move invalidate_location to resource.c.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Invalidate containers via callback.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Remove surface_invalidate_location.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Move bitmap_data and user_memory into the resource.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Move load_location into the resource.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Replace surface_load_location with resource_load_location.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Introduce helper functions for mapping volumes.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Move volume PBO infrastructure into the resource.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Remove surface->pbo.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Use resource buffer mapping facilities in surfaces.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Move buffer creation into the resource.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Handle WINED3D_LOCATION_DISCARDED in surface_load_texture.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Handle LOCATION_DISCARDED in surface_load_drawable.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Handle WINED3D_LOCATION_DISCARDED for sysmem loads.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Discard implicit surfaces on unload.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Don'\''t try to flip sysmem copies in swapchain_present.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Discard the backbuffer in discard presents.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Allocate sysmem for client storage if it doesn'\''t exist already.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Introduce a function to retrieve resource memory.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Make surface_ops->unmap specific for front buffers.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Move check_block_align to resource.c.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Replace surface alloc functions with resource ones.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Don'\''t delete the buffer in surface_cleanup.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Use resource facilities to destroy PBOs.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Move simple location copying to the resource.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Move most of volume_map to resource.c.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Use resource_map for surface_map.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Use client storage with DIB sections.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Don'\''t call the public map function in surface_convert_format.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Don'\''t call the public map function in surface_cpu_blt.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Move the framebuffer into wined3d_state.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Get rid of state access in shader_generate_glsl_declarations.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Preload buffers if streamsrc is not dirty.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Hackily introduce a multithreaded command stream.", 1 },'; \ + echo '+ { "Henri Verbeet", "wined3d: Wait for resource updates to finish when using the multithreaded command stream.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Don'\''t store pointers in struct wined3d_cs_present.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Don'\''t put rectangle pointers into wined3d_cs_clear.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Store the color in clear ops instead of a pointer.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Pass the state to draw_primitive.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Wait for the cs before destroying objects.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Give the cs its own state.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Send float constant updates through the command stream.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Request a glFinish before modifying resources outside the cs.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Finish the cs before changing the texture lod.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Don'\''t call glFinish after clears.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Don'\''t call glFinish after draws.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Shadow device->offscreenBuffer in the context.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Don'\''t access the stateblock in find_draw_buffers_mask.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Pass the depth stencil to swapchain->present.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Don'\''t store viewport pointers in the command stream.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Keep track of the onscreen depth stencil in the command stream instead of the device.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Send base vertex index updates through the cs.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Send primitive type updates through the command stream.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Send bool constant updates through the command stream.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Send int constant updates through the command stream.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Send light updates through the command stream.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Prevent the command stream from running ahead too far.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Wait for the cs to finish before destroying the device.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Run the cs asynchronously.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Send blits through the command stream.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Put update_surface checks back in place.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Get rid of WINED3D_BUFFER_FLUSH.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Add cs waiting debug code.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Don'\''t force strict draw ordering for multithreaded CS.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Send render target view clears through the command stream.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Wait for the CS in GetDC.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: send resource maps through the command stream.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Get rid of the end_scene flush and finish.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Replace the linked lists with a ringbuffer.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Don'\''t preload buffers on unmap.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Don'\''t call glFinish before swapping.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: wined3d_*_query_issue never fails.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Add query support to the command stream.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Check our CS state to find out if a query is done.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Poll queries automatically in the CS.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Introduce a separate queue for priority commands.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Destroy queries through the CS.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Separate main and worker thread query state.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Don'\''t poll queries that failed to start.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Remove restated queries from the poll list.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Don'\''t reset the query state if it doesn'\''t have a ctx.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Put this into the query poll patch.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Send update_surface commands through the CS.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Send texture preloads through the CS.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Send surface preloads through the CS.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Send update_texture calls through the CS.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Get rid of the surface_upload_data glFinish.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Don'\''t lock the src volume in device_update_volume.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Handle evit_managed_resources through the CS.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Send flips through the command stream.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Introduce resource fencing.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Fence update_texture and update_surface calls.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Dirtify resources on unmap.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Fence texture reads in draws.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Fence render targets and depth stencils.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Fence blit operations.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Fence color_fill operations.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Fence clear calls.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Fence present calls.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Make resource maps and unmaps a priority command.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Dirtify changed textures through the command stream.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Wrap GL BOs in a structure.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Separate resource map and draw buffers.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Implement DISCARD resource maps with buffers.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Implement DISCARD resource maps with heap memory.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Unset some objects in state_init_default.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Don'\''t request the frontbuffer to create dummy textures.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Use double-buffered buffers for multithreaded CS.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Don'\''t synchronize NOOVERWRITE buffer maps.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Separate buffer map write and draw read memory pointers.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Accelerate DISCARD buffer maps.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Accelerate READONLY buffer maps.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Access the buffer dirty areas through the CS.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Ignore buffer->resource.map_count in the CS.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Send buffer preloads through the CS.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Use glBufferSubData instead of glMapBufferRange.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Separate GL buffer discard control from ignoring MAP_DISCARD.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Create buffers before mapping them.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Destroy views through the CS.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Remove another glFinish.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Destroy vertex declarations through the CS.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Destroy shaders through the CS.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Create VBOs through the command stream.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Clean up resource data through the CS.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Clean up buffer resource data through the CS.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Clean up volume resource data through the CS.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Clean up surfaces through the cs.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Clean up texture resources through the cs.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Unload resources through the CS in uninit_3d.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Unload resources through the CS in device_reset.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Don'\''t glFinish after a depth buffer blit.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Remove software cursor support.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Create dummy textures through the CS.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Create the initial context through the CS.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Recreate ctx and dummy textures through the CS after resets.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Ignore WINED3D_MAP_NO_DIRTY_UPDATE in resource_map.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Delete GL contexts through the CS in reset.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Delete GL contexts through the CS in uninit_3d.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Invoke surface_unload through the CS in wined3d_surface_update_desc.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Use an event to block the worker thread when it is idle.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Fence preload operations.", 1 },'; \ + echo '+ { "Stefan Dösinger", "d3d8/tests: D3DLOCK_NO_DIRTY_UPDATE on managed textures is temporarily broken.", 1 },'; \ + echo '+ { "Stefan Dösinger", "d3d9/tests: D3DLOCK_NO_DIRTY_UPDATE on managed textures is temporarily broken.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Completely reset the state on reset.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Send getdc and releasedc through the command stream.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Set map_heap_memory = NULL when allocating a PBO.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Wait only for the buffer to be idle.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Add a comment about worker thread lag.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Remove the texture destroy glFinish.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Move FBO destruction into the worker thread.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Don'\''t incref / decref textures in color / depth fill blits.", 1 },'; \ + echo '+ { "Stefan Dösinger", "Winex11: complain about glfinish.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Make sure the new window is set up before setting up a context.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Remove the device_reset CS sync fixme.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Put GL_APPLE_flush_buffer_range syncing back in place.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Wait for the resource to be idle when destroying user memory surfaces.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Don'\''t sync on redundant discard calls.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Don'\''t discard new buffers.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Don'\''t try to sync VBOs manually on OSX with CSMT.", 1 },'; \ + echo '+ { "Stefan Dösinger", "wined3d: Render target lock hack.", 1 },'; \ + echo '+ { "Matteo Bruni", "wined3d: Avoid calling wined3d_surface_blt() from surface_upload_from_surface().", 1 },'; \ + echo '+ { "Sebastian Lackner", "wined3d: Fix some uninitialized memory accesses.", 1 },'; \ + echo '+ { "Sebastian Lackner", "wined3d: Enable CSMT by default, print a winediag message informing about this patchset.", 1 },'; \ + echo '+ { "Wine Staging Team", "Autogenerated #ifdef patch for wined3d-CSMT_Main.", 1 },'; \ + ) > wined3d-CSMT_Main.ok + # Patchset wined3d-DXTn # | # | This patchset fixes the following Wine bugs: diff --git a/patches/wined3d-CSMT_Helper/0001-wined3d-Merge-get_pitch-functions.patch b/patches/wined3d-CSMT_Helper/0001-wined3d-Merge-get_pitch-functions.patch new file mode 100644 index 00000000..50045184 --- /dev/null +++ b/patches/wined3d-CSMT_Helper/0001-wined3d-Merge-get_pitch-functions.patch @@ -0,0 +1,406 @@ +From e40fbe3feb09e745a7cb95413b23f3087a2859af Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 19 Sep 2013 14:22:24 +0200 +Subject: wined3d: Merge get_pitch functions. + +--- + dlls/ddraw/surface.c | 12 ++++++-- + dlls/wined3d/resource.c | 31 +++++++++++++++++++ + dlls/wined3d/surface.c | 70 +++++++++++++++++------------------------- + dlls/wined3d/volume.c | 29 ++--------------- + dlls/wined3d/wined3d.spec | 2 +- + dlls/wined3d/wined3d_private.h | 2 +- + include/wine/wined3d.h | 3 +- + 7 files changed, 74 insertions(+), 75 deletions(-) + +diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c +index a4184b8..a0d7f2d 100644 +--- a/dlls/ddraw/surface.c ++++ b/dlls/ddraw/surface.c +@@ -6158,6 +6158,10 @@ void ddraw_surface_init(struct ddraw_surface *surface, struct ddraw *ddraw, stru + DDSURFACEDESC2 *desc = &surface->surface_desc; + struct wined3d_resource_desc wined3d_desc; + unsigned int version = texture->version; ++ UINT row_pitch, slice_pitch; ++ struct wined3d_resource *resource = wined3d_surface_get_resource(wined3d_surface); ++ ++ wined3d_resource_get_pitch(resource, &row_pitch, &slice_pitch); + + surface->IDirectDrawSurface7_iface.lpVtbl = &ddraw_surface7_vtbl; + surface->IDirectDrawSurface4_iface.lpVtbl = &ddraw_surface4_vtbl; +@@ -6188,7 +6192,7 @@ void ddraw_surface_init(struct ddraw_surface *surface, struct ddraw *ddraw, stru + } + + *desc = texture->surface_desc; +- wined3d_resource_get_desc(wined3d_surface_get_resource(wined3d_surface), &wined3d_desc); ++ wined3d_resource_get_desc(resource, &wined3d_desc); + desc->dwWidth = wined3d_desc.width; + desc->dwHeight = wined3d_desc.height; + surface->first_attached = surface; +@@ -6198,14 +6202,16 @@ void ddraw_surface_init(struct ddraw_surface *surface, struct ddraw *ddraw, stru + if (desc->dwFlags & DDSD_LPSURFACE) + desc->u1.dwLinearSize = ~0u; + else +- desc->u1.dwLinearSize = wined3d_surface_get_pitch(wined3d_surface) * ((desc->dwHeight + 3) / 4); ++ { ++ desc->u1.dwLinearSize = row_pitch * ((desc->dwHeight + 3) / 4); ++ } + desc->dwFlags |= DDSD_LINEARSIZE; + desc->dwFlags &= ~(DDSD_LPSURFACE | DDSD_PITCH); + } + else + { + if (!(desc->dwFlags & DDSD_LPSURFACE)) +- desc->u1.lPitch = wined3d_surface_get_pitch(wined3d_surface); ++ desc->u1.lPitch = row_pitch; + desc->dwFlags |= DDSD_PITCH; + desc->dwFlags &= ~(DDSD_LPSURFACE | DDSD_LINEARSIZE); + } +diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c +index 0ab55dc..8032a4c 100644 +--- a/dlls/wined3d/resource.c ++++ b/dlls/wined3d/resource.c +@@ -331,3 +331,34 @@ void wined3d_resource_update_draw_binding(struct wined3d_resource *resource) + else + resource->draw_binding = WINED3D_LOCATION_TEXTURE_RGB; + } ++ ++void CDECL wined3d_resource_get_pitch(const struct wined3d_resource *resource, UINT *row_pitch, ++ UINT *slice_pitch) ++{ ++ unsigned int alignment; ++ const struct wined3d_format *format = resource->format; ++ ++ if (resource->custom_row_pitch) ++ { ++ *row_pitch = resource->custom_row_pitch; ++ *slice_pitch = resource->custom_slice_pitch; ++ return; ++ } ++ ++ alignment = resource->device->surface_alignment; ++ *row_pitch = wined3d_format_calculate_pitch(resource->format, resource->width); ++ *row_pitch = (*row_pitch + alignment - 1) & ~(alignment - 1); ++ if (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 slice_block_count = (resource->height + format->block_height - 1) / format->block_height; ++ *slice_pitch = *row_pitch * slice_block_count; ++ } ++ else ++ { ++ *slice_pitch = *row_pitch * resource->height; ++ } ++ ++ TRACE("Returning row pitch %u, slice pitch %u.\n", *row_pitch, *slice_pitch); ++} +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 092cbe6..d9b1846 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -364,6 +364,7 @@ static HRESULT surface_create_dib_section(struct wined3d_surface *surface) + BITMAPINFO *b_info; + int extraline = 0; + DWORD *masks; ++ UINT row_pitch, slice_pitch; + + TRACE("surface %p.\n", surface); + +@@ -409,10 +410,11 @@ static HRESULT surface_create_dib_section(struct wined3d_surface *surface) + + b_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + /* TODO: Is there a nicer way to force a specific alignment? (8 byte for ddraw) */ +- b_info->bmiHeader.biWidth = wined3d_surface_get_pitch(surface) / format->byte_count; ++ wined3d_resource_get_pitch(&surface->resource, &row_pitch, &slice_pitch); ++ b_info->bmiHeader.biWidth = row_pitch / format->byte_count; + b_info->bmiHeader.biHeight = 0 - surface->resource.height - extraline; + b_info->bmiHeader.biSizeImage = (surface->resource.height + extraline) +- * wined3d_surface_get_pitch(surface); ++ * row_pitch; + b_info->bmiHeader.biPlanes = 1; + b_info->bmiHeader.biBitCount = format->byte_count * 8; + +@@ -1359,14 +1361,14 @@ static void surface_download_data(struct wined3d_surface *surface, const struct + void *mem; + GLenum gl_format = format->glFormat; + GLenum gl_type = format->glType; +- int src_pitch = 0; +- int dst_pitch = 0; ++ UINT src_pitch = 0; ++ UINT dst_row_pitch, dst_slice_pitch; + + if (surface->flags & SFLAG_NONPOW2) + { + unsigned char alignment = surface->resource.device->surface_alignment; + src_pitch = format->byte_count * surface->pow2Width; +- dst_pitch = wined3d_surface_get_pitch(surface); ++ wined3d_resource_get_pitch(&surface->resource, &dst_row_pitch, &dst_slice_pitch); + src_pitch = (src_pitch + alignment - 1) & ~(alignment - 1); + mem = HeapAlloc(GetProcessHeap(), 0, src_pitch * surface->pow2Height); + } +@@ -1453,12 +1455,12 @@ static void surface_download_data(struct wined3d_surface *surface, const struct + * won't be released, and doesn't have to be re-read. */ + src_data = mem; + dst_data = data.addr; +- TRACE("(%p) : Repacking the surface data from pitch %d to pitch %d\n", surface, src_pitch, dst_pitch); ++ TRACE("(%p) : Repacking the surface data from pitch %d to pitch %d\n", surface, src_pitch, dst_row_pitch); + for (y = 0; y < surface->resource.height; ++y) + { +- memcpy(dst_data, src_data, dst_pitch); ++ memcpy(dst_data, src_data, dst_row_pitch); + src_data += src_pitch; +- dst_data += dst_pitch; ++ dst_data += dst_row_pitch; + } + + HeapFree(GetProcessHeap(), 0, mem); +@@ -1612,7 +1614,7 @@ HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface, const P + UINT update_w, update_h; + UINT dst_w, dst_h; + RECT r, dst_rect; +- UINT src_pitch; ++ UINT src_row_pitch, src_slice_pitch; + POINT p; + + TRACE("dst_surface %p, dst_point %s, src_surface %p, src_rect %s.\n", +@@ -1698,9 +1700,9 @@ HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface, const P + wined3d_texture_bind(dst_surface->container, context, FALSE); + + surface_get_memory(src_surface, &data, src_surface->locations); +- src_pitch = wined3d_surface_get_pitch(src_surface); ++ wined3d_resource_get_pitch(&src_surface->resource, &src_row_pitch, &src_slice_pitch); + +- surface_upload_data(dst_surface, gl_info, src_format, src_rect, src_pitch, dst_point, FALSE, &data); ++ surface_upload_data(dst_surface, gl_info, src_format, src_rect, src_row_pitch, dst_point, FALSE, &data); + + context_invalidate_active_texture(context); + +@@ -2008,25 +2010,6 @@ HRESULT CDECL wined3d_surface_restore(struct wined3d_surface *surface) + return WINED3D_OK; + } + +-DWORD CDECL wined3d_surface_get_pitch(const struct wined3d_surface *surface) +-{ +- unsigned int alignment; +- DWORD pitch; +- +- TRACE("surface %p.\n", surface); +- +- if (surface->pitch) +- return surface->pitch; +- +- alignment = surface->resource.device->surface_alignment; +- pitch = wined3d_format_calculate_pitch(surface->resource.format, surface->resource.width); +- pitch = (pitch + alignment - 1) & ~(alignment - 1); +- +- TRACE("Returning %u.\n", pitch); +- +- return pitch; +-} +- + HRESULT CDECL wined3d_surface_set_overlay_position(struct wined3d_surface *surface, LONG x, LONG y) + { + LONG w, h; +@@ -2207,12 +2190,13 @@ HRESULT wined3d_surface_update_desc(struct wined3d_surface *surface, + surface->resource.map_binding = WINED3D_LOCATION_USER_MEMORY; + valid_location = WINED3D_LOCATION_USER_MEMORY; + } +- surface->pitch = pitch; ++ surface->resource.custom_row_pitch = pitch; ++ surface->resource.custom_slice_pitch = pitch * surface->resource.height; + surface->resource.format = texture_resource->format; + surface->resource.multisample_type = texture_resource->multisample_type; + surface->resource.multisample_quality = texture_resource->multisample_quality; +- if (surface->pitch) +- surface->resource.size = height * surface->pitch; ++ if (surface->resource.custom_row_pitch) ++ surface->resource.size = height * surface->resource.custom_row_pitch; + else + surface->resource.size = wined3d_format_calculate_size(texture_resource->format, + texture_resource->device->surface_alignment, width, height, 1); +@@ -2680,7 +2664,7 @@ HRESULT CDECL wined3d_surface_map(struct wined3d_surface *surface, + if (format->flags & WINED3DFMT_FLAG_BROKEN_PITCH) + map_desc->row_pitch = surface->resource.width * format->byte_count; + else +- map_desc->row_pitch = wined3d_surface_get_pitch(surface); ++ wined3d_resource_get_pitch(&surface->resource, &map_desc->row_pitch, &map_desc->slice_pitch); + map_desc->slice_pitch = 0; + + if (!rect) +@@ -2860,7 +2844,9 @@ static void read_from_framebuffer(struct wined3d_surface *surface, DWORD dst_loc + { + /* glReadPixels returns the image upside down, and there is no way to prevent this. + * Flip the lines in software. */ +- UINT pitch = wined3d_surface_get_pitch(surface); ++ UINT pitch, slice_pitch; ++ ++ wined3d_resource_get_pitch(&surface->resource, &pitch, &slice_pitch); + + if (!(row = HeapAlloc(GetProcessHeap(), 0, pitch))) + goto error; +@@ -4092,7 +4078,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + const struct wined3d_color_key_conversion *conversion; + struct wined3d_texture *texture = surface->container; + struct wined3d_context *context; +- UINT width, src_pitch, dst_pitch; ++ UINT width, src_row_pitch, src_slice_pitch, dst_pitch; + struct wined3d_bo_address data; + struct wined3d_format format; + POINT dst_point = {0, 0}; +@@ -4187,7 +4173,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + else surface->flags &= ~SFLAG_GLCKEY; + + width = surface->resource.width; +- src_pitch = wined3d_surface_get_pitch(surface); ++ wined3d_resource_get_pitch(&surface->resource, &src_row_pitch, &src_slice_pitch); + + format = *texture->resource.format; + if ((conversion = wined3d_format_get_color_key_conversion(texture, TRUE))) +@@ -4226,9 +4212,9 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + context_release(context); + return E_OUTOFMEMORY; + } +- format.convert(data.addr, mem, src_pitch, src_pitch * height, ++ format.convert(data.addr, mem, src_row_pitch, src_row_pitch * height, + dst_pitch, dst_pitch * height, width, height, 1); +- src_pitch = dst_pitch; ++ src_row_pitch = dst_pitch; + data.addr = mem; + } + else if (conversion) +@@ -4248,13 +4234,13 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + } + if (texture->swapchain && texture->swapchain->palette) + palette = texture->swapchain->palette; +- conversion->convert(data.addr, src_pitch, mem, dst_pitch, ++ conversion->convert(data.addr, src_row_pitch, mem, dst_pitch, + width, height, palette, &texture->src_blt_color_key); +- src_pitch = dst_pitch; ++ src_row_pitch = dst_pitch; + data.addr = mem; + } + +- surface_upload_data(surface, gl_info, &format, &src_rect, src_pitch, &dst_point, srgb, &data); ++ surface_upload_data(surface, gl_info, &format, &src_rect, src_row_pitch, &dst_point, srgb, &data); + + context_release(context); + +diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c +index 58d7321..af99825 100644 +--- a/dlls/wined3d/volume.c ++++ b/dlls/wined3d/volume.c +@@ -40,31 +40,6 @@ BOOL volume_prepare_system_memory(struct wined3d_volume *volume) + return TRUE; + } + +-static 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 (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); +-} +- + /* Context activation is done by the caller. */ + void wined3d_volume_upload_data(struct wined3d_volume *volume, const struct wined3d_context *context, + const struct wined3d_bo_address *data) +@@ -95,7 +70,7 @@ void wined3d_volume_upload_data(struct wined3d_volume *volume, const struct wine + dst_row_pitch = (dst_row_pitch + alignment - 1) & ~(alignment - 1); + dst_slice_pitch = dst_row_pitch * height; + +- wined3d_volume_get_pitch(volume, &src_row_pitch, &src_slice_pitch); ++ wined3d_resource_get_pitch(&volume->resource, &src_row_pitch, &src_slice_pitch); + + mem = HeapAlloc(GetProcessHeap(), 0, dst_slice_pitch * depth); + format->convert(data->addr, mem, src_row_pitch, src_slice_pitch, +@@ -638,7 +613,7 @@ HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume, + } + else + { +- wined3d_volume_get_pitch(volume, &map_desc->row_pitch, &map_desc->slice_pitch); ++ wined3d_resource_get_pitch(&volume->resource, &map_desc->row_pitch, &map_desc->slice_pitch); + } + + if (!box) +diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec +index 7a77003..95885c7 100644 +--- a/dlls/wined3d/wined3d.spec ++++ b/dlls/wined3d/wined3d.spec +@@ -181,6 +181,7 @@ + + @ cdecl wined3d_resource_get_desc(ptr ptr) + @ cdecl wined3d_resource_get_parent(ptr) ++@ cdecl wined3d_resource_get_pitch(ptr ptr ptr) + @ cdecl wined3d_resource_get_priority(ptr) + @ cdecl wined3d_resource_set_parent(ptr ptr) + @ cdecl wined3d_resource_set_priority(ptr long) +@@ -226,7 +227,6 @@ + @ cdecl wined3d_surface_get_flip_status(ptr long) + @ cdecl wined3d_surface_get_overlay_position(ptr ptr ptr) + @ cdecl wined3d_surface_get_parent(ptr) +-@ cdecl wined3d_surface_get_pitch(ptr) + @ cdecl wined3d_surface_get_render_target_data(ptr ptr) + @ cdecl wined3d_surface_get_resource(ptr) + @ cdecl wined3d_surface_getdc(ptr ptr) +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 7935a5d..abd8d2b 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2080,6 +2080,7 @@ struct wined3d_resource + UINT size; + DWORD priority; + void *heap_memory; ++ UINT custom_row_pitch, custom_slice_pitch; + struct list resource_list_entry; + + void *parent; +@@ -2298,7 +2299,6 @@ struct wined3d_surface + + DWORD flags; + +- UINT pitch; + UINT pow2Width; + UINT pow2Height; + +diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h +index 0cf26e1..3d24b98 100644 +--- a/include/wine/wined3d.h ++++ b/include/wine/wined3d.h +@@ -2411,6 +2411,8 @@ static inline HRESULT wined3d_private_store_set_private_data(struct wined3d_priv + void __cdecl wined3d_resource_get_desc(const struct wined3d_resource *resource, + struct wined3d_resource_desc *desc); + void * __cdecl wined3d_resource_get_parent(const struct wined3d_resource *resource); ++void __cdecl wined3d_resource_get_pitch(const struct wined3d_resource *resource, UINT *row_pitch, ++ UINT *slice_pitch); + DWORD __cdecl wined3d_resource_get_priority(const struct wined3d_resource *resource); + void __cdecl wined3d_resource_set_parent(struct wined3d_resource *resource, void *parent); + DWORD __cdecl wined3d_resource_set_priority(struct wined3d_resource *resource, DWORD priority); +@@ -2468,7 +2470,6 @@ HRESULT __cdecl wined3d_surface_get_blt_status(const struct wined3d_surface *sur + HRESULT __cdecl wined3d_surface_get_flip_status(const struct wined3d_surface *surface, DWORD flags); + HRESULT __cdecl wined3d_surface_get_overlay_position(const struct wined3d_surface *surface, LONG *x, LONG *y); + void * __cdecl wined3d_surface_get_parent(const struct wined3d_surface *surface); +-DWORD __cdecl wined3d_surface_get_pitch(const struct wined3d_surface *surface); + HRESULT __cdecl wined3d_surface_get_render_target_data(struct wined3d_surface *surface, + struct wined3d_surface *render_target); + struct wined3d_resource * __cdecl wined3d_surface_get_resource(struct wined3d_surface *surface); +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Helper/definition b/patches/wined3d-CSMT_Helper/definition new file mode 100644 index 00000000..e69de29b diff --git a/patches/wined3d-CSMT_Main/0001-wined3d-Pass-a-context-to-surface_load_sysmem.patch b/patches/wined3d-CSMT_Main/0001-wined3d-Pass-a-context-to-surface_load_sysmem.patch new file mode 100644 index 00000000..6c8a7df9 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0001-wined3d-Pass-a-context-to-surface_load_sysmem.patch @@ -0,0 +1,79 @@ +From d802d551603f20fde872cf45d43064426bea4434 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Sun, 17 Nov 2013 19:10:18 +0100 +Subject: wined3d: Pass a context to surface_load_sysmem. + +--- + dlls/wined3d/surface.c | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index d9b1846..3877139 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -4010,9 +4010,12 @@ static void surface_copy_simple_location(struct wined3d_surface *surface, DWORD + memcpy(dst.addr, src.addr, size); + } + ++/* Context activation is done by the caller. */ + static void surface_load_sysmem(struct wined3d_surface *surface, +- const struct wined3d_gl_info *gl_info, DWORD dst_location) ++ struct wined3d_context *context, DWORD dst_location) + { ++ const struct wined3d_gl_info *gl_info = context->gl_info; ++ + if (surface->locations & surface_simple_locations) + { + surface_copy_simple_location(surface, dst_location); +@@ -4025,18 +4028,10 @@ static void surface_load_sysmem(struct wined3d_surface *surface, + /* Download the surface to system memory. */ + if (surface->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) + { +- struct wined3d_device *device = surface->resource.device; +- struct wined3d_context *context; +- +- /* TODO: Use already acquired context when possible. */ +- context = context_acquire(device, NULL); +- + wined3d_texture_bind_and_dirtify(surface->container, context, + !(surface->locations & WINED3D_LOCATION_TEXTURE_RGB)); + surface_download_data(surface, gl_info, dst_location); + +- context_release(context); +- + return; + } + +@@ -4266,6 +4261,7 @@ HRESULT surface_load_location(struct wined3d_surface *surface, DWORD location) + struct wined3d_device *device = surface->resource.device; + const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; + HRESULT hr; ++ struct wined3d_context *context = NULL; + + TRACE("surface %p, location %s.\n", surface, wined3d_debug_location(location)); + +@@ -4274,7 +4270,7 @@ HRESULT surface_load_location(struct wined3d_surface *surface, DWORD location) + if (location == WINED3D_LOCATION_TEXTURE_RGB + && surface->locations & (WINED3D_LOCATION_DRAWABLE | WINED3D_LOCATION_DISCARDED)) + { +- struct wined3d_context *context = context_acquire(device, NULL); ++ context = context_acquire(device, NULL); + surface_load_ds_location(surface, context, location); + context_release(context); + return WINED3D_OK; +@@ -4320,7 +4316,11 @@ HRESULT surface_load_location(struct wined3d_surface *surface, DWORD location) + case WINED3D_LOCATION_USER_MEMORY: + case WINED3D_LOCATION_SYSMEM: + case WINED3D_LOCATION_BUFFER: +- surface_load_sysmem(surface, gl_info, location); ++ if (device->d3d_initialized) ++ context = context_acquire(device, NULL); ++ surface_load_sysmem(surface, context, location); ++ if (context) ++ context_release(context); + break; + + case WINED3D_LOCATION_DRAWABLE: +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0002-wined3d-Pass-a-context-to-read_from_framebuffer.patch b/patches/wined3d-CSMT_Main/0002-wined3d-Pass-a-context-to-read_from_framebuffer.patch new file mode 100644 index 00000000..195fefcc --- /dev/null +++ b/patches/wined3d-CSMT_Main/0002-wined3d-Pass-a-context-to-read_from_framebuffer.patch @@ -0,0 +1,81 @@ +From e29e2b0ccda7ed5e930eb18b3c73204150a68123 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Sun, 17 Nov 2013 19:16:40 +0100 +Subject: wined3d: Pass a context to read_from_framebuffer. + +In the average case the function will not be able to reuse it, because +it requires a specific context to access the WGL framebuffer. It will +restore the original context afterwards to hide the context change from +load_location / preload callers. This is related to bug 34574. +--- + dlls/wined3d/surface.c | 29 +++++++++++++++++++++++++---- + 1 file changed, 25 insertions(+), 4 deletions(-) + +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 3877139..ef6a233 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -2781,11 +2781,13 @@ HRESULT CDECL wined3d_surface_releasedc(struct wined3d_surface *surface, HDC dc) + return WINED3D_OK; + } + +-static void read_from_framebuffer(struct wined3d_surface *surface, DWORD dst_location) ++static void read_from_framebuffer(struct wined3d_surface *surface, ++ struct wined3d_context *old_ctx, DWORD dst_location) + { + struct wined3d_device *device = surface->resource.device; + const struct wined3d_gl_info *gl_info; + struct wined3d_context *context; ++ struct wined3d_surface *restore_rt; + BYTE *mem; + BYTE *row, *top, *bottom; + int i; +@@ -2794,7 +2796,21 @@ static void read_from_framebuffer(struct wined3d_surface *surface, DWORD dst_loc + + surface_get_memory(surface, &data, dst_location); + +- context = context_acquire(device, surface); ++ /* Context_release does not restore the original context in case of ++ * nested context_acquire calls. Only read_from_framebuffer and ++ * surface_blt_to_drawable use nested context_acquire calls. Manually ++ * restore the original context at the end of the function if needed. */ ++ if (old_ctx->current_rt == surface) ++ { ++ restore_rt = NULL; ++ context = old_ctx; ++ } ++ else ++ { ++ restore_rt = old_ctx->current_rt; ++ context = context_acquire(device, surface); ++ } ++ + context_apply_blit_state(context, device); + gl_info = context->gl_info; + +@@ -2882,7 +2898,12 @@ error: + checkGLcall("glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0)"); + } + +- context_release(context); ++ if (restore_rt) ++ { ++ context_release(context); ++ context = context_acquire(device, restore_rt); ++ context_release(context); ++ } + } + + /* Read the framebuffer contents into a texture. Note that this function +@@ -4037,7 +4058,7 @@ static void surface_load_sysmem(struct wined3d_surface *surface, + + if (surface->locations & WINED3D_LOCATION_DRAWABLE) + { +- read_from_framebuffer(surface, dst_location); ++ read_from_framebuffer(surface, context, dst_location); + return; + } + +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0003-wined3d-Pass-a-context-to-surface_load_drawable-and-.patch b/patches/wined3d-CSMT_Main/0003-wined3d-Pass-a-context-to-surface_load_drawable-and-.patch new file mode 100644 index 00000000..b225c80b --- /dev/null +++ b/patches/wined3d-CSMT_Main/0003-wined3d-Pass-a-context-to-surface_load_drawable-and-.patch @@ -0,0 +1,121 @@ +From da5210457d0a852e97fd20fed4b33030585b0549 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Sun, 17 Nov 2013 19:34:26 +0100 +Subject: wined3d: Pass a context to surface_load_drawable and + surface_blt_to_drawable. + +--- + dlls/wined3d/surface.c | 40 ++++++++++++++++++++++++++++++++++------ + 1 file changed, 34 insertions(+), 6 deletions(-) + +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index ef6a233..7a32f7f 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -3452,19 +3452,35 @@ void surface_translate_drawable_coords(const struct wined3d_surface *surface, HW + rect->bottom = drawable_height - rect->bottom; + } + ++/* Context activation is done by the caller. */ + static void surface_blt_to_drawable(const struct wined3d_device *device, ++ struct wined3d_context *old_ctx, + enum wined3d_texture_filter_type filter, BOOL alpha_test, + struct wined3d_surface *src_surface, const RECT *src_rect_in, + struct wined3d_surface *dst_surface, const RECT *dst_rect_in) + { + const struct wined3d_gl_info *gl_info; + struct wined3d_context *context; ++ struct wined3d_surface *restore_rt; + RECT src_rect, dst_rect; + + src_rect = *src_rect_in; + dst_rect = *dst_rect_in; + +- context = context_acquire(device, dst_surface); ++ /* Context_release does not restore the original context in case of ++ * nested context_acquire calls. Only read_from_framebuffer and ++ * surface_blt_to_drawable use nested context_acquire calls. Manually ++ * restore the original context at the end of the function if needed. */ ++ if (old_ctx->current_rt == dst_surface) ++ { ++ restore_rt = NULL; ++ context = old_ctx; ++ } ++ else ++ { ++ restore_rt = old_ctx->current_rt; ++ context = context_acquire(device, dst_surface); ++ } + gl_info = context->gl_info; + + /* Make sure the surface is up-to-date. This should probably use +@@ -3517,7 +3533,12 @@ static void surface_blt_to_drawable(const struct wined3d_device *device, + && dst_surface->container->swapchain->front_buffer == dst_surface->container)) + gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ + +- context_release(context); ++ if (restore_rt) ++ { ++ context_release(context); ++ context = context_acquire(device, restore_rt); ++ context_release(context); ++ } + } + + HRESULT surface_color_fill(struct wined3d_surface *s, const RECT *rect, const struct wined3d_color *color) +@@ -3668,6 +3689,7 @@ static HRESULT surface_blt_special(struct wined3d_surface *dst_surface, const RE + /* Blit from offscreen surface to render target */ + struct wined3d_color_key old_blt_key = src_surface->container->src_blt_color_key; + DWORD old_color_key_flags = src_surface->container->color_key_flags; ++ struct wined3d_context *context; + + TRACE("Blt from surface %p to rendertarget %p\n", src_surface, dst_surface); + +@@ -3701,9 +3723,11 @@ static HRESULT surface_blt_special(struct wined3d_surface *dst_surface, const RE + wined3d_texture_set_color_key(src_surface->container, WINEDDSD_CKSRCBLT, NULL); + } + +- surface_blt_to_drawable(device, filter, ++ context = context_acquire(device, dst_surface); ++ surface_blt_to_drawable(device, context, filter, + flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYSRCOVERRIDE | WINEDDBLT_ALPHATEST), + src_surface, src_rect, dst_surface, dst_rect); ++ context_release(context); + + /* Restore the color key parameters */ + wined3d_texture_set_color_key(src_surface->container, WINEDDSD_CKSRCBLT, +@@ -4066,8 +4090,9 @@ static void surface_load_sysmem(struct wined3d_surface *surface, + surface, wined3d_debug_location(surface->locations)); + } + ++/* Context activation is done by the caller. */ + static HRESULT surface_load_drawable(struct wined3d_surface *surface, +- const struct wined3d_gl_info *gl_info) ++ struct wined3d_context *context) + { + RECT r; + +@@ -4080,7 +4105,7 @@ static HRESULT surface_load_drawable(struct wined3d_surface *surface, + + surface_get_rect(surface, NULL, &r); + surface_load_location(surface, WINED3D_LOCATION_TEXTURE_RGB); +- surface_blt_to_drawable(surface->resource.device, ++ surface_blt_to_drawable(surface->resource.device, context, + WINED3D_TEXF_POINT, FALSE, surface, &r, surface, &r); + + return WINED3D_OK; +@@ -4345,7 +4370,10 @@ HRESULT surface_load_location(struct wined3d_surface *surface, DWORD location) + break; + + case WINED3D_LOCATION_DRAWABLE: +- if (FAILED(hr = surface_load_drawable(surface, gl_info))) ++ context = context_acquire(device, NULL); ++ hr = surface_load_drawable(surface, context); ++ context_release(context); ++ if (FAILED(hr)) + return hr; + break; + +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0004-wined3d-Pass-a-context-to-surface_blt_fbo.patch b/patches/wined3d-CSMT_Main/0004-wined3d-Pass-a-context-to-surface_blt_fbo.patch new file mode 100644 index 00000000..d2efde0a --- /dev/null +++ b/patches/wined3d-CSMT_Main/0004-wined3d-Pass-a-context-to-surface_blt_fbo.patch @@ -0,0 +1,140 @@ +From 61070d97c76557046a90cac37fbdf9c5f033adb4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Sun, 17 Nov 2013 19:49:38 +0100 +Subject: wined3d: Pass a context to surface_blt_fbo. + +--- + dlls/wined3d/surface.c | 53 +++++++++++++++++++++++++++++++++++++++----------- + 1 file changed, 42 insertions(+), 11 deletions(-) + +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 7a32f7f..a2f8112 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -860,13 +860,15 @@ static void surface_depth_blt_fbo(const struct wined3d_device *device, + } + + /* Blit between surface locations. Onscreen on different swapchains is not supported. +- * Depth / stencil is not supported. */ +-static void surface_blt_fbo(const struct wined3d_device *device, enum wined3d_texture_filter_type filter, ++ * Depth / stencil is not supported. Context activation is done by the caller. */ ++static void surface_blt_fbo(const struct wined3d_device *device, ++ struct wined3d_context *old_ctx, enum wined3d_texture_filter_type filter, + struct wined3d_surface *src_surface, DWORD src_location, const RECT *src_rect_in, + struct wined3d_surface *dst_surface, DWORD dst_location, const RECT *dst_rect_in) + { + const struct wined3d_gl_info *gl_info; + struct wined3d_context *context; ++ struct wined3d_surface *required_rt, *restore_rt; + RECT src_rect, dst_rect; + GLenum gl_filter; + GLenum buffer; +@@ -909,9 +911,20 @@ static void surface_blt_fbo(const struct wined3d_device *device, enum wined3d_te + if (!surface_is_full_rect(dst_surface, &dst_rect)) + surface_load_location(dst_surface, dst_location); + +- if (src_location == WINED3D_LOCATION_DRAWABLE) context = context_acquire(device, src_surface); +- else if (dst_location == WINED3D_LOCATION_DRAWABLE) context = context_acquire(device, dst_surface); +- else context = context_acquire(device, NULL); ++ if (src_location == WINED3D_LOCATION_DRAWABLE) required_rt = src_surface; ++ else if (dst_location == WINED3D_LOCATION_DRAWABLE) required_rt = dst_surface; ++ else required_rt = NULL; ++ ++ if (required_rt && required_rt != old_ctx->current_rt) ++ { ++ restore_rt = context->current_rt; ++ context = context_acquire(device, required_rt); ++ } ++ else ++ { ++ restore_rt = NULL; ++ context = old_ctx; ++ } + + if (!context->valid) + { +@@ -974,7 +987,12 @@ static void surface_blt_fbo(const struct wined3d_device *device, enum wined3d_te + && dst_surface->container->swapchain->front_buffer == dst_surface->container)) + gl_info->gl_ops.gl.p_glFlush(); + +- context_release(context); ++ if (restore_rt) ++ { ++ context_release(context); ++ context = context_acquire(device, restore_rt); ++ context_release(context); ++ } + } + + static BOOL fbo_blit_supported(const struct wined3d_gl_info *gl_info, enum wined3d_blit_op blit_op, +@@ -4140,13 +4158,17 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + NULL, surface->resource.usage, surface->resource.pool, surface->resource.format, + NULL, surface->resource.usage, surface->resource.pool, surface->resource.format)) + { ++ context = context_acquire(device, NULL); ++ + if (srgb) +- surface_blt_fbo(device, WINED3D_TEXF_POINT, surface, WINED3D_LOCATION_TEXTURE_RGB, ++ surface_blt_fbo(device, context, WINED3D_TEXF_POINT, surface, WINED3D_LOCATION_TEXTURE_RGB, + &src_rect, surface, WINED3D_LOCATION_TEXTURE_SRGB, &src_rect); + else +- surface_blt_fbo(device, WINED3D_TEXF_POINT, surface, WINED3D_LOCATION_TEXTURE_SRGB, ++ surface_blt_fbo(device, context, WINED3D_TEXF_POINT, surface, WINED3D_LOCATION_TEXTURE_SRGB, + &src_rect, surface, WINED3D_LOCATION_TEXTURE_RGB, &src_rect); + ++ context_release(context); ++ + return WINED3D_OK; + } + +@@ -4161,8 +4183,10 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + DWORD dst_location = srgb ? WINED3D_LOCATION_TEXTURE_SRGB : WINED3D_LOCATION_TEXTURE_RGB; + RECT rect = {0, 0, surface->resource.width, surface->resource.height}; + +- surface_blt_fbo(device, WINED3D_TEXF_POINT, surface, src_location, ++ context = context_acquire(device, NULL); ++ surface_blt_fbo(device, context, WINED3D_TEXF_POINT, surface, src_location, + &rect, surface, dst_location, &rect); ++ context_release(context); + + return WINED3D_OK; + } +@@ -4292,14 +4316,17 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + + static void surface_multisample_resolve(struct wined3d_surface *surface) + { ++ struct wined3d_context *context; + RECT rect = {0, 0, surface->resource.width, surface->resource.height}; + + if (!(surface->locations & WINED3D_LOCATION_RB_MULTISAMPLE)) + ERR("Trying to resolve multisampled surface %p, but location WINED3D_LOCATION_RB_MULTISAMPLE not current.\n", + surface); + +- surface_blt_fbo(surface->resource.device, WINED3D_TEXF_POINT, ++ context = context_acquire(surface->resource.device, NULL); ++ surface_blt_fbo(surface->resource.device, context, WINED3D_TEXF_POINT, + surface, WINED3D_LOCATION_RB_MULTISAMPLE, &rect, surface, WINED3D_LOCATION_RB_RESOLVED, &rect); ++ context_release(context); + } + + HRESULT surface_load_location(struct wined3d_surface *surface, DWORD location) +@@ -5474,11 +5501,15 @@ HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const REC + &src_rect, src_surface->resource.usage, src_surface->resource.pool, src_surface->resource.format, + &dst_rect, dst_surface->resource.usage, dst_surface->resource.pool, dst_surface->resource.format)) + { ++ struct wined3d_context *context; + TRACE("Using FBO blit.\n"); + +- surface_blt_fbo(device, filter, ++ context = context_acquire(device, NULL); ++ surface_blt_fbo(device, context, filter, + src_surface, src_surface->container->resource.draw_binding, &src_rect, + dst_surface, dst_surface->container->resource.draw_binding, &dst_rect); ++ context_release(context); ++ + surface_validate_location(dst_surface, dst_surface->container->resource.draw_binding); + surface_invalidate_location(dst_surface, ~dst_surface->container->resource.draw_binding); + +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0005-wined3d-Pass-a-context-to-surface_multisample_resolv.patch b/patches/wined3d-CSMT_Main/0005-wined3d-Pass-a-context-to-surface_multisample_resolv.patch new file mode 100644 index 00000000..01fe3ab7 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0005-wined3d-Pass-a-context-to-surface_multisample_resolv.patch @@ -0,0 +1,49 @@ +From f3cecdde174e3fc350ca4a35771183695b6777de Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Sun, 17 Nov 2013 19:50:47 +0100 +Subject: wined3d: Pass a context to surface_multisample_resolve. + +--- + dlls/wined3d/surface.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index a2f8112..ee6cfdd 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -4314,19 +4314,17 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + return WINED3D_OK; + } + +-static void surface_multisample_resolve(struct wined3d_surface *surface) ++/* Context activation is done by the caller. */ ++static void surface_multisample_resolve(struct wined3d_surface *surface, struct wined3d_context *context) + { +- struct wined3d_context *context; + RECT rect = {0, 0, surface->resource.width, surface->resource.height}; + + if (!(surface->locations & WINED3D_LOCATION_RB_MULTISAMPLE)) + ERR("Trying to resolve multisampled surface %p, but location WINED3D_LOCATION_RB_MULTISAMPLE not current.\n", + surface); + +- context = context_acquire(surface->resource.device, NULL); + surface_blt_fbo(surface->resource.device, context, WINED3D_TEXF_POINT, + surface, WINED3D_LOCATION_RB_MULTISAMPLE, &rect, surface, WINED3D_LOCATION_RB_RESOLVED, &rect); +- context_release(context); + } + + HRESULT surface_load_location(struct wined3d_surface *surface, DWORD location) +@@ -4405,7 +4403,9 @@ HRESULT surface_load_location(struct wined3d_surface *surface, DWORD location) + break; + + case WINED3D_LOCATION_RB_RESOLVED: +- surface_multisample_resolve(surface); ++ context = context_acquire(device, NULL); ++ surface_multisample_resolve(surface, context); ++ context_release(context); + break; + + case WINED3D_LOCATION_TEXTURE_RGB: +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0006-wined3d-Pass-a-context-to-surface_load_texture.patch b/patches/wined3d-CSMT_Main/0006-wined3d-Pass-a-context-to-surface_load_texture.patch new file mode 100644 index 00000000..8d565d48 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0006-wined3d-Pass-a-context-to-surface_load_texture.patch @@ -0,0 +1,100 @@ +From c47fbee59422dcccdf545d9ca1a37eba75e7ef92 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Sun, 17 Nov 2013 19:52:56 +0100 +Subject: wined3d: Pass a context to surface_load_texture. + +--- + dlls/wined3d/surface.c | 21 ++++++--------------- + 1 file changed, 6 insertions(+), 15 deletions(-) + +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index ee6cfdd..b37dca9 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -4130,13 +4130,13 @@ static HRESULT surface_load_drawable(struct wined3d_surface *surface, + } + + static HRESULT surface_load_texture(struct wined3d_surface *surface, +- const struct wined3d_gl_info *gl_info, BOOL srgb) ++ struct wined3d_context *context, BOOL srgb) + { ++ const struct wined3d_gl_info *gl_info = context->gl_info; + RECT src_rect = {0, 0, surface->resource.width, surface->resource.height}; + struct wined3d_device *device = surface->resource.device; + const struct wined3d_color_key_conversion *conversion; + struct wined3d_texture *texture = surface->container; +- struct wined3d_context *context; + UINT width, src_row_pitch, src_slice_pitch, dst_pitch; + struct wined3d_bo_address data; + struct wined3d_format format; +@@ -4158,8 +4158,6 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + NULL, surface->resource.usage, surface->resource.pool, surface->resource.format, + NULL, surface->resource.usage, surface->resource.pool, surface->resource.format)) + { +- context = context_acquire(device, NULL); +- + if (srgb) + surface_blt_fbo(device, context, WINED3D_TEXF_POINT, surface, WINED3D_LOCATION_TEXTURE_RGB, + &src_rect, surface, WINED3D_LOCATION_TEXTURE_SRGB, &src_rect); +@@ -4167,8 +4165,6 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + surface_blt_fbo(device, context, WINED3D_TEXF_POINT, surface, WINED3D_LOCATION_TEXTURE_SRGB, + &src_rect, surface, WINED3D_LOCATION_TEXTURE_RGB, &src_rect); + +- context_release(context); +- + return WINED3D_OK; + } + +@@ -4183,10 +4179,8 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + DWORD dst_location = srgb ? WINED3D_LOCATION_TEXTURE_SRGB : WINED3D_LOCATION_TEXTURE_RGB; + RECT rect = {0, 0, surface->resource.width, surface->resource.height}; + +- context = context_acquire(device, NULL); + surface_blt_fbo(device, context, WINED3D_TEXF_POINT, surface, src_location, + &rect, surface, dst_location, &rect); +- context_release(context); + + return WINED3D_OK; + } +@@ -4224,9 +4218,6 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + surface_load_location(surface, WINED3D_LOCATION_SYSMEM); + } + +- /* TODO: Use already acquired context when possible. */ +- context = context_acquire(device, NULL); +- + wined3d_texture_prepare_texture(texture, context, srgb); + wined3d_texture_bind_and_dirtify(texture, context, srgb); + +@@ -4307,8 +4298,6 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + + surface_upload_data(surface, gl_info, &format, &src_rect, src_row_pitch, &dst_point, srgb, &data); + +- context_release(context); +- + HeapFree(GetProcessHeap(), 0, mem); + + return WINED3D_OK; +@@ -4330,7 +4319,6 @@ static void surface_multisample_resolve(struct wined3d_surface *surface, struct + HRESULT surface_load_location(struct wined3d_surface *surface, DWORD location) + { + struct wined3d_device *device = surface->resource.device; +- const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; + HRESULT hr; + struct wined3d_context *context = NULL; + +@@ -4410,7 +4398,10 @@ HRESULT surface_load_location(struct wined3d_surface *surface, DWORD location) + + case WINED3D_LOCATION_TEXTURE_RGB: + case WINED3D_LOCATION_TEXTURE_SRGB: +- if (FAILED(hr = surface_load_texture(surface, gl_info, location == WINED3D_LOCATION_TEXTURE_SRGB))) ++ context = context_acquire(device, NULL); ++ hr = surface_load_texture(surface, context, location == WINED3D_LOCATION_TEXTURE_SRGB); ++ context_release(context); ++ if (FAILED(hr)) + return hr; + break; + +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0007-wined3d-Pass-a-context-to-surface_load_location.patch b/patches/wined3d-CSMT_Main/0007-wined3d-Pass-a-context-to-surface_load_location.patch new file mode 100644 index 00000000..cb11a1d3 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0007-wined3d-Pass-a-context-to-surface_load_location.patch @@ -0,0 +1,543 @@ +From c6a152077c4e86728448103b7fdc72463d723c7c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Sun, 17 Nov 2013 20:19:24 +0100 +Subject: wined3d: Pass a context to surface_load_location. + +--- + dlls/wined3d/context.c | 4 +- + dlls/wined3d/device.c | 20 +++---- + dlls/wined3d/drawprim.c | 20 +++---- + dlls/wined3d/surface.c | 122 +++++++++++++++++++++++++---------------- + dlls/wined3d/swapchain.c | 8 +-- + dlls/wined3d/texture.c | 7 ++- + dlls/wined3d/wined3d_private.h | 5 +- + 7 files changed, 108 insertions(+), 78 deletions(-) + +diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c +index 4da8c7d..1f34992 100644 +--- a/dlls/wined3d/context.c ++++ b/dlls/wined3d/context.c +@@ -2199,7 +2199,7 @@ static BOOL match_depth_stencil_format(const struct wined3d_format *existing, + return TRUE; + } + +-/* The caller provides a context */ ++/* Context activation is done by the caller. */ + static void context_validate_onscreen_formats(struct wined3d_context *context, + const struct wined3d_rendertarget_view *depth_stencil) + { +@@ -2215,7 +2215,7 @@ static void context_validate_onscreen_formats(struct wined3d_context *context, + WARN("Depth stencil format is not supported by WGL, rendering the backbuffer in an FBO\n"); + + /* The currently active context is the necessary context to access the swapchain's onscreen buffers */ +- surface_load_location(context->current_rt, WINED3D_LOCATION_TEXTURE_RGB); ++ surface_load_location(context->current_rt, context, WINED3D_LOCATION_TEXTURE_RGB); + swapchain->render_to_fbo = TRUE; + swapchain_update_draw_bindings(swapchain); + context_set_render_offscreen(context, TRUE); +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index 89ec00a..0b4c6f9 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -300,6 +300,15 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c + unsigned int i; + RECT ds_rect; + ++ context = context_acquire(device, target); ++ if (!context->valid) ++ { ++ context_release(context); ++ WARN("Invalid context, skipping clear.\n"); ++ return; ++ } ++ gl_info = context->gl_info; ++ + /* When we're clearing parts of the drawable, make sure that the target surface is well up to date in the + * drawable. After the clear we'll mark the drawable up to date, so we have to make sure that this is true + * for the cleared parts, and the untouched parts. +@@ -314,19 +323,10 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c + { + struct wined3d_surface *rt = wined3d_rendertarget_view_get_surface(fb->render_targets[i]); + if (rt) +- surface_load_location(rt, rt->container->resource.draw_binding); ++ surface_load_location(rt, context, rt->container->resource.draw_binding); + } + } + +- context = context_acquire(device, target); +- if (!context->valid) +- { +- context_release(context); +- WARN("Invalid context, skipping clear.\n"); +- return; +- } +- gl_info = context->gl_info; +- + if (target) + { + render_offscreen = context->render_offscreen; +diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c +index 265942c..2d39a83 100644 +--- a/dlls/wined3d/drawprim.c ++++ b/dlls/wined3d/drawprim.c +@@ -608,6 +608,15 @@ void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_co + + if (!index_count) return; + ++ context = context_acquire(device, wined3d_rendertarget_view_get_surface(device->fb.render_targets[0])); ++ if (!context->valid) ++ { ++ context_release(context); ++ WARN("Invalid context, skipping draw.\n"); ++ return; ++ } ++ gl_info = context->gl_info; ++ + if (state->render_states[WINED3D_RS_COLORWRITEENABLE]) + { + /* Invalidate the back buffer memory so LockRect will read it the next time */ +@@ -616,21 +625,12 @@ void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_co + struct wined3d_surface *target = wined3d_rendertarget_view_get_surface(device->fb.render_targets[i]); + if (target) + { +- surface_load_location(target, target->container->resource.draw_binding); ++ surface_load_location(target, context, target->container->resource.draw_binding); + surface_invalidate_location(target, ~target->container->resource.draw_binding); + } + } + } + +- context = context_acquire(device, wined3d_rendertarget_view_get_surface(device->fb.render_targets[0])); +- if (!context->valid) +- { +- context_release(context); +- WARN("Invalid context, skipping draw.\n"); +- return; +- } +- gl_info = context->gl_info; +- + if (device->fb.depth_stencil) + { + /* Note that this depends on the context_acquire() call above to set +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index b37dca9..66956df 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -753,7 +753,16 @@ static void surface_unmap(struct wined3d_surface *surface) + } + + if (surface->container->swapchain && surface->container->swapchain->front_buffer == surface->container) +- surface_load_location(surface, surface->container->resource.draw_binding); ++ { ++ struct wined3d_device *device = surface->resource.device; ++ struct wined3d_context *context = NULL; ++ ++ if (device->d3d_initialized) ++ context = context_acquire(device, surface); ++ surface_load_location(surface, context, surface->container->resource.draw_binding); ++ if (context) ++ context_release(context); ++ } + else if (surface->resource.format->flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) + FIXME("Depth / stencil buffer locking is not implemented.\n"); + } +@@ -806,12 +815,6 @@ static void surface_depth_blt_fbo(const struct wined3d_device *device, + if (src_mask & WINED3DFMT_FLAG_STENCIL) + gl_mask |= GL_STENCIL_BUFFER_BIT; + +- /* Make sure the locations are up-to-date. Loading the destination +- * surface isn't required if the entire surface is overwritten. */ +- surface_load_location(src_surface, src_location); +- if (!surface_is_full_rect(dst_surface, dst_rect)) +- surface_load_location(dst_surface, dst_location); +- + context = context_acquire(device, NULL); + if (!context->valid) + { +@@ -820,6 +823,12 @@ static void surface_depth_blt_fbo(const struct wined3d_device *device, + return; + } + ++ /* Make sure the locations are up-to-date. Loading the destination ++ * surface isn't required if the entire surface is overwritten. */ ++ surface_load_location(src_surface, context, src_location); ++ if (!surface_is_full_rect(dst_surface, dst_rect)) ++ surface_load_location(dst_surface, context, dst_location); ++ + gl_info = context->gl_info; + + context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, NULL, src_surface, src_location); +@@ -907,9 +916,9 @@ static void surface_blt_fbo(const struct wined3d_device *device, + * surface isn't required if the entire surface is overwritten. (And is + * in fact harmful if we're being called by surface_load_location() with + * the purpose of loading the destination surface.) */ +- surface_load_location(src_surface, src_location); ++ surface_load_location(src_surface, old_ctx, src_location); + if (!surface_is_full_rect(dst_surface, &dst_rect)) +- surface_load_location(dst_surface, dst_location); ++ surface_load_location(dst_surface, old_ctx, dst_location); + + if (src_location == WINED3D_LOCATION_DRAWABLE) required_rt = src_surface; + else if (dst_location == WINED3D_LOCATION_DRAWABLE) required_rt = dst_surface; +@@ -1199,6 +1208,9 @@ static void surface_unload(struct wined3d_resource *resource) + + TRACE("surface %p.\n", surface); + ++ context = context_acquire(device, NULL); ++ gl_info = context->gl_info; ++ + if (resource->pool == WINED3D_POOL_DEFAULT) + { + /* Default pool resources are supposed to be destroyed before Reset is called. +@@ -1224,13 +1236,10 @@ static void surface_unload(struct wined3d_resource *resource) + else + { + surface_prepare_map_memory(surface); +- surface_load_location(surface, surface->resource.map_binding); ++ surface_load_location(surface, context, surface->resource.map_binding); + surface_invalidate_location(surface, ~surface->resource.map_binding); + } + +- context = context_acquire(device, NULL); +- gl_info = context->gl_info; +- + /* Destroy PBOs, but load them into real sysmem before */ + if (surface->pbo) + surface_remove_pbo(surface, gl_info); +@@ -1714,7 +1723,7 @@ HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface, const P + if (update_w == dst_w && update_h == dst_h) + wined3d_texture_prepare_texture(dst_surface->container, context, FALSE); + else +- surface_load_location(dst_surface, WINED3D_LOCATION_TEXTURE_RGB); ++ surface_load_location(dst_surface, context, WINED3D_LOCATION_TEXTURE_RGB); + wined3d_texture_bind(dst_surface->container, context, FALSE); + + surface_get_memory(src_surface, &data, src_surface->locations); +@@ -1831,7 +1840,8 @@ GLenum surface_get_gl_buffer(const struct wined3d_surface *surface) + return GL_BACK; + } + +-void surface_load(struct wined3d_surface *surface, BOOL srgb) ++/* Context activation is done by the caller. */ ++void surface_load(struct wined3d_surface *surface, struct wined3d_context *context, BOOL srgb) + { + DWORD location = srgb ? WINED3D_LOCATION_TEXTURE_SRGB : WINED3D_LOCATION_TEXTURE_RGB; + BOOL ck_changed; +@@ -1856,7 +1866,7 @@ void surface_load(struct wined3d_surface *surface, BOOL srgb) + * the surface. Make sure we have it. */ + + surface_prepare_map_memory(surface); +- surface_load_location(surface, surface->resource.map_binding); ++ surface_load_location(surface, context, surface->resource.map_binding); + surface_invalidate_location(surface, ~surface->resource.map_binding); + /* Switching color keying on / off may change the internal format. */ + if (ck_changed) +@@ -1872,7 +1882,7 @@ void surface_load(struct wined3d_surface *surface, BOOL srgb) + return; + } + +- surface_load_location(surface, location); ++ surface_load_location(surface, context, location); + surface_evict_sysmem(surface); + } + +@@ -2639,10 +2649,16 @@ HRESULT CDECL wined3d_surface_map(struct wined3d_surface *surface, + } + else + { ++ struct wined3d_context *context = NULL; ++ + if (surface->resource.usage & WINED3DUSAGE_DYNAMIC) + WARN_(d3d_perf)("Mapping a dynamic surface without WINED3D_MAP_DISCARD.\n"); + +- surface_load_location(surface, surface->resource.map_binding); ++ if (surface->resource.device->d3d_initialized) ++ context = context_acquire(surface->resource.device, NULL); ++ surface_load_location(surface, context, surface->resource.map_binding); ++ if (context) ++ context_release(context); + } + + if (!(flags & (WINED3D_MAP_NO_DIRTY_UPDATE | WINED3D_MAP_READONLY))) +@@ -2724,6 +2740,8 @@ HRESULT CDECL wined3d_surface_map(struct wined3d_surface *surface, + HRESULT CDECL wined3d_surface_getdc(struct wined3d_surface *surface, HDC *dc) + { + HRESULT hr; ++ struct wined3d_device *device = surface->resource.device; ++ struct wined3d_context *context = NULL; + + TRACE("surface %p, dc %p.\n", surface, dc); + +@@ -2735,26 +2753,36 @@ HRESULT CDECL wined3d_surface_getdc(struct wined3d_surface *surface, HDC *dc) + if (surface->resource.map_count) + return WINED3DERR_INVALIDCALL; + ++ if (device->d3d_initialized) ++ context = context_acquire(surface->resource.device, NULL); ++ + /* Create a DIB section if there isn't a dc yet. */ + if (!surface->hDC) + { + if (surface->flags & SFLAG_CLIENT) + { +- surface_load_location(surface, WINED3D_LOCATION_SYSMEM); ++ surface_load_location(surface, context, WINED3D_LOCATION_SYSMEM); + surface_release_client_storage(surface); + } + hr = surface_create_dib_section(surface); + if (FAILED(hr)) +- return WINED3DERR_INVALIDCALL; ++ { ++ if (context) ++ context_release(context); ++ return WINED3DERR_INVALIDCALL; ++ } + if (!(surface->resource.map_binding == WINED3D_LOCATION_USER_MEMORY + || surface->container->flags & WINED3D_TEXTURE_PIN_SYSMEM + || surface->pbo)) + surface->resource.map_binding = WINED3D_LOCATION_DIB; + } + +- surface_load_location(surface, WINED3D_LOCATION_DIB); ++ surface_load_location(surface, context, WINED3D_LOCATION_DIB); + surface_invalidate_location(surface, ~WINED3D_LOCATION_DIB); + ++ if (context) ++ context_release(context); ++ + surface->flags |= SFLAG_DCINUSE; + surface->resource.map_count++; + +@@ -2792,8 +2820,16 @@ HRESULT CDECL wined3d_surface_releasedc(struct wined3d_surface *surface, HDC dc) + * copied back to the DIB in the next getdc call. + * + * The same consideration applies to user memory surfaces. */ +- surface_load_location(surface, surface->resource.map_binding); ++ struct wined3d_device *device = surface->resource.device; ++ struct wined3d_context *context = NULL; ++ ++ if (device->d3d_initialized) ++ context = context_acquire(device, NULL); ++ ++ surface_load_location(surface, context, surface->resource.map_binding); + surface_invalidate_location(surface, WINED3D_LOCATION_DIB); ++ if (context) ++ context_release(context); + } + + return WINED3D_OK; +@@ -4086,7 +4122,7 @@ static void surface_load_sysmem(struct wined3d_surface *surface, + } + + if (surface->locations & (WINED3D_LOCATION_RB_MULTISAMPLE | WINED3D_LOCATION_RB_RESOLVED)) +- surface_load_location(surface, WINED3D_LOCATION_TEXTURE_RGB); ++ surface_load_location(surface, context, WINED3D_LOCATION_TEXTURE_RGB); + + /* Download the surface to system memory. */ + if (surface->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) +@@ -4122,7 +4158,7 @@ static HRESULT surface_load_drawable(struct wined3d_surface *surface, + } + + surface_get_rect(surface, NULL, &r); +- surface_load_location(surface, WINED3D_LOCATION_TEXTURE_RGB); ++ surface_load_location(surface, context, WINED3D_LOCATION_TEXTURE_RGB); + surface_blt_to_drawable(surface->resource.device, context, + WINED3D_TEXF_POINT, FALSE, surface, &r, surface, &r); + +@@ -4195,7 +4231,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + /* Performance warning... */ + FIXME("Downloading RGB surface %p to reload it as sRGB.\n", surface); + surface_prepare_map_memory(surface); +- surface_load_location(surface, surface->resource.map_binding); ++ surface_load_location(surface, context, surface->resource.map_binding); + } + } + else +@@ -4206,7 +4242,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + /* Performance warning... */ + FIXME("Downloading sRGB surface %p to reload it as RGB.\n", surface); + surface_prepare_map_memory(surface); +- surface_load_location(surface, surface->resource.map_binding); ++ surface_load_location(surface, context, surface->resource.map_binding); + } + } + +@@ -4215,7 +4251,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + WARN("Trying to load a texture from sysmem, but no simple location is valid.\n"); + /* Lets hope we get it from somewhere... */ + surface_prepare_system_memory(surface); +- surface_load_location(surface, WINED3D_LOCATION_SYSMEM); ++ surface_load_location(surface, context, WINED3D_LOCATION_SYSMEM); + } + + wined3d_texture_prepare_texture(texture, context, srgb); +@@ -4248,7 +4284,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + surface->resource.map_binding = WINED3D_LOCATION_SYSMEM; + + surface_prepare_map_memory(surface); +- surface_load_location(surface, surface->resource.map_binding); ++ surface_load_location(surface, context, surface->resource.map_binding); + surface_remove_pbo(surface, gl_info); + } + +@@ -4316,11 +4352,10 @@ static void surface_multisample_resolve(struct wined3d_surface *surface, struct + surface, WINED3D_LOCATION_RB_MULTISAMPLE, &rect, surface, WINED3D_LOCATION_RB_RESOLVED, &rect); + } + +-HRESULT surface_load_location(struct wined3d_surface *surface, DWORD location) ++/* Context activation is done by the caller. Context may be NULL in ddraw-only mode. */ ++HRESULT surface_load_location(struct wined3d_surface *surface, struct wined3d_context *context, DWORD location) + { +- struct wined3d_device *device = surface->resource.device; + HRESULT hr; +- struct wined3d_context *context = NULL; + + TRACE("surface %p, location %s.\n", surface, wined3d_debug_location(location)); + +@@ -4329,9 +4364,7 @@ HRESULT surface_load_location(struct wined3d_surface *surface, DWORD location) + if (location == WINED3D_LOCATION_TEXTURE_RGB + && surface->locations & (WINED3D_LOCATION_DRAWABLE | WINED3D_LOCATION_DISCARDED)) + { +- context = context_acquire(device, NULL); + surface_load_ds_location(surface, context, location); +- context_release(context); + return WINED3D_OK; + } + else if (location & surface->locations +@@ -4375,33 +4408,22 @@ HRESULT surface_load_location(struct wined3d_surface *surface, DWORD location) + case WINED3D_LOCATION_USER_MEMORY: + case WINED3D_LOCATION_SYSMEM: + case WINED3D_LOCATION_BUFFER: +- if (device->d3d_initialized) +- context = context_acquire(device, NULL); + surface_load_sysmem(surface, context, location); +- if (context) +- context_release(context); + break; + + case WINED3D_LOCATION_DRAWABLE: +- context = context_acquire(device, NULL); +- hr = surface_load_drawable(surface, context); +- context_release(context); +- if (FAILED(hr)) ++ if (FAILED(hr = surface_load_drawable(surface, context))) + return hr; + break; + + case WINED3D_LOCATION_RB_RESOLVED: +- context = context_acquire(device, NULL); + surface_multisample_resolve(surface, context); +- context_release(context); + break; + + case WINED3D_LOCATION_TEXTURE_RGB: + case WINED3D_LOCATION_TEXTURE_SRGB: +- context = context_acquire(device, NULL); +- hr = surface_load_texture(surface, context, location == WINED3D_LOCATION_TEXTURE_SRGB); +- context_release(context); +- if (FAILED(hr)) ++ if (FAILED(hr = surface_load_texture(surface, context, ++ location == WINED3D_LOCATION_TEXTURE_SRGB))) + return hr; + break; + +@@ -5459,7 +5481,11 @@ HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const REC + if (SUCCEEDED(surface_upload_from_surface(dst_surface, &dst_point, src_surface, &src_rect))) + { + if (!wined3d_resource_is_offscreen(&dst_surface->container->resource)) +- surface_load_location(dst_surface, dst_surface->container->resource.draw_binding); ++ { ++ struct wined3d_context *context = context_acquire(device, dst_surface); ++ surface_load_location(dst_surface, context, dst_surface->container->resource.draw_binding); ++ context_release(context); ++ } + return WINED3D_OK; + } + } +diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c +index 887143f..d742b11 100644 +--- a/dlls/wined3d/swapchain.c ++++ b/dlls/wined3d/swapchain.c +@@ -309,7 +309,7 @@ static void swapchain_blit(const struct wined3d_swapchain *swapchain, + if (backbuffer->resource.multisample_type) + { + location = WINED3D_LOCATION_RB_RESOLVED; +- surface_load_location(backbuffer, location); ++ surface_load_location(backbuffer, context, location); + } + + context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, backbuffer, NULL, location); +@@ -511,14 +511,14 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT + */ + if (!swapchain->render_to_fbo && render_to_fbo && wined3d_settings.offscreen_rendering_mode == ORM_FBO) + { +- surface_load_location(back_buffer, WINED3D_LOCATION_TEXTURE_RGB); ++ 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, back_buffer->container->resource.draw_binding); ++ surface_load_location(back_buffer, context, back_buffer->container->resource.draw_binding); + } + + if (swapchain->render_to_fbo) +@@ -640,7 +640,7 @@ void x11_copy_to_screen(const struct wined3d_swapchain *swapchain, const RECT *r + + TRACE("Copying surface %p to screen.\n", front); + +- surface_load_location(front, WINED3D_LOCATION_DIB); ++ surface_load_location(front, NULL, WINED3D_LOCATION_DIB); + + src_dc = front->hDC; + window = swapchain->win_handle; +diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c +index 6ecd414..c173518 100644 +--- a/dlls/wined3d/texture.c ++++ b/dlls/wined3d/texture.c +@@ -819,16 +819,19 @@ HRESULT CDECL wined3d_texture_add_dirty_region(struct wined3d_texture *texture, + static void texture2d_sub_resource_load(struct wined3d_resource *sub_resource, + struct wined3d_context *context, BOOL srgb) + { +- surface_load(surface_from_resource(sub_resource), srgb); ++ surface_load(surface_from_resource(sub_resource), context, srgb); + } + + static void texture2d_sub_resource_add_dirty_region(struct wined3d_resource *sub_resource, + const struct wined3d_box *dirty_region) + { + struct wined3d_surface *surface = surface_from_resource(sub_resource); ++ struct wined3d_context *context; + + surface_prepare_map_memory(surface); +- surface_load_location(surface, surface->resource.map_binding); ++ 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); + } + +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index abd8d2b..7115eca 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2350,11 +2350,12 @@ GLenum surface_get_gl_buffer(const struct wined3d_surface *surface) DECLSPEC_HID + void surface_get_drawable_size(const struct wined3d_surface *surface, const struct wined3d_context *context, + unsigned int *width, unsigned int *height) DECLSPEC_HIDDEN; + void surface_invalidate_location(struct wined3d_surface *surface, DWORD location) DECLSPEC_HIDDEN; +-void surface_load(struct wined3d_surface *surface, BOOL srgb) 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) DECLSPEC_HIDDEN; +-HRESULT surface_load_location(struct wined3d_surface *surface, DWORD location) DECLSPEC_HIDDEN; ++HRESULT surface_load_location(struct wined3d_surface *surface, ++ struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN; + void surface_modify_ds_location(struct wined3d_surface *surface, DWORD location, UINT w, UINT h) DECLSPEC_HIDDEN; + void surface_prepare_rb(struct wined3d_surface *surface, + const struct wined3d_gl_info *gl_info, BOOL multisample) DECLSPEC_HIDDEN; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0008-wined3d-Make-surface_load_location-return-nothing.patch b/patches/wined3d-CSMT_Main/0008-wined3d-Make-surface_load_location-return-nothing.patch new file mode 100644 index 00000000..d8a34826 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0008-wined3d-Make-surface_load_location-return-nothing.patch @@ -0,0 +1,106 @@ +From 7059ae36100e7efafcbcefcf582c34c0ce99e435 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Sun, 17 Nov 2013 20:25:01 +0100 +Subject: wined3d: Make surface_load_location return nothing. + +--- + dlls/wined3d/surface.c | 18 +++++++++--------- + dlls/wined3d/wined3d_private.h | 2 +- + 2 files changed, 10 insertions(+), 10 deletions(-) + +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 66956df..8a14169 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -4353,7 +4353,7 @@ static void surface_multisample_resolve(struct wined3d_surface *surface, struct + } + + /* Context activation is done by the caller. Context may be NULL in ddraw-only mode. */ +-HRESULT surface_load_location(struct wined3d_surface *surface, struct wined3d_context *context, DWORD location) ++void surface_load_location(struct wined3d_surface *surface, struct wined3d_context *context, DWORD location) + { + HRESULT hr; + +@@ -4365,26 +4365,26 @@ HRESULT surface_load_location(struct wined3d_surface *surface, struct wined3d_co + && surface->locations & (WINED3D_LOCATION_DRAWABLE | WINED3D_LOCATION_DISCARDED)) + { + surface_load_ds_location(surface, context, location); +- return WINED3D_OK; ++ return; + } + else if (location & surface->locations + && surface->container->resource.draw_binding != WINED3D_LOCATION_DRAWABLE) + { + /* Already up to date, nothing to do. */ +- return WINED3D_OK; ++ return; + } + else + { + FIXME("Unimplemented copy from %s to %s for depth/stencil buffers.\n", + wined3d_debug_location(surface->locations), wined3d_debug_location(location)); +- return WINED3DERR_INVALIDCALL; ++ return; + } + } + + if (surface->locations & location) + { + TRACE("Location already up to date.\n"); +- return WINED3D_OK; ++ return; + } + + if (WARN_ON(d3d_surface)) +@@ -4399,7 +4399,7 @@ HRESULT surface_load_location(struct wined3d_surface *surface, struct wined3d_co + { + ERR("Surface %p does not have any up to date location.\n", surface); + surface->flags |= SFLAG_LOST; +- return WINED3DERR_DEVICELOST; ++ return; + } + + switch (location) +@@ -4413,7 +4413,7 @@ HRESULT surface_load_location(struct wined3d_surface *surface, struct wined3d_co + + case WINED3D_LOCATION_DRAWABLE: + if (FAILED(hr = surface_load_drawable(surface, context))) +- return hr; ++ return; + break; + + case WINED3D_LOCATION_RB_RESOLVED: +@@ -4424,7 +4424,7 @@ HRESULT surface_load_location(struct wined3d_surface *surface, struct wined3d_co + case WINED3D_LOCATION_TEXTURE_SRGB: + if (FAILED(hr = surface_load_texture(surface, context, + location == WINED3D_LOCATION_TEXTURE_SRGB))) +- return hr; ++ return; + break; + + default: +@@ -4437,7 +4437,7 @@ HRESULT surface_load_location(struct wined3d_surface *surface, struct wined3d_co + if (location != WINED3D_LOCATION_SYSMEM && (surface->locations & WINED3D_LOCATION_SYSMEM)) + surface_evict_sysmem(surface); + +- return WINED3D_OK; ++ return; + } + + static HRESULT ffp_blit_alloc(struct wined3d_device *device) { return WINED3D_OK; } +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 7115eca..f24808b 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2354,7 +2354,7 @@ void surface_load(struct wined3d_surface *surface, struct wined3d_context *conte + 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) DECLSPEC_HIDDEN; +-HRESULT surface_load_location(struct wined3d_surface *surface, ++void surface_load_location(struct wined3d_surface *surface, + struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN; + void surface_modify_ds_location(struct wined3d_surface *surface, DWORD location, UINT w, UINT h) DECLSPEC_HIDDEN; + void surface_prepare_rb(struct wined3d_surface *surface, +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0009-wined3d-Store-volume-locations-in-the-resource.patch b/patches/wined3d-CSMT_Main/0009-wined3d-Store-volume-locations-in-the-resource.patch new file mode 100644 index 00000000..8d7eefc0 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0009-wined3d-Store-volume-locations-in-the-resource.patch @@ -0,0 +1,203 @@ +From 98ce21ea2f7c29d885b7dcf5b36819f8d977c5a5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 3 Oct 2013 12:31:24 +0200 +Subject: wined3d: Store volume locations in the resource. + +--- + dlls/wined3d/volume.c | 46 +++++++++++++++++++++--------------------- + dlls/wined3d/wined3d_private.h | 5 +++-- + 2 files changed, 26 insertions(+), 25 deletions(-) + +diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c +index af99825..ea56b38 100644 +--- a/dlls/wined3d/volume.c ++++ b/dlls/wined3d/volume.c +@@ -101,15 +101,15 @@ void wined3d_volume_upload_data(struct wined3d_volume *volume, const struct wine + static 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)); ++ volume->resource.locations |= location; ++ TRACE("new location flags are %s.\n", wined3d_debug_location(volume->resource.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)); ++ volume->resource.locations &= ~location; ++ TRACE("new location flags are %s.\n", wined3d_debug_location(volume->resource.locations)); + } + + /* Context activation is done by the caller. */ +@@ -217,9 +217,9 @@ static void wined3d_volume_load_location(struct wined3d_volume *volume, + 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)); ++ wined3d_debug_location(volume->resource.locations)); + +- if ((volume->locations & location) == location) ++ if ((volume->resource.locations & location) == location) + { + TRACE("Location(s) already up to date.\n"); + return; +@@ -242,32 +242,32 @@ static void wined3d_volume_load_location(struct wined3d_volume *volume, + && !(volume->container->flags & WINED3D_TEXTURE_SRGB_ALLOCATED))) + ERR("Trying to load (s)RGB texture without prior allocation.\n"); + +- if (volume->locations & WINED3D_LOCATION_DISCARDED) ++ if (volume->resource.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) ++ else if (volume->resource.locations & WINED3D_LOCATION_SYSMEM) + { + struct wined3d_bo_address data = {0, volume->resource.heap_memory}; + wined3d_volume_upload_data(volume, context, &data); + } +- else if (volume->locations & WINED3D_LOCATION_BUFFER) ++ else if (volume->resource.locations & WINED3D_LOCATION_BUFFER) + { + struct wined3d_bo_address data = {volume->pbo, NULL}; + wined3d_volume_upload_data(volume, context, &data); + } +- else if (volume->locations & WINED3D_LOCATION_TEXTURE_RGB) ++ else if (volume->resource.locations & WINED3D_LOCATION_TEXTURE_RGB) + { + wined3d_volume_srgb_transfer(volume, context, TRUE); + } +- else if (volume->locations & WINED3D_LOCATION_TEXTURE_SRGB) ++ else if (volume->resource.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)); ++ FIXME("Implement texture loading from %s.\n", wined3d_debug_location(volume->resource.locations)); + return; + } + wined3d_volume_validate_location(volume, location); +@@ -281,16 +281,16 @@ static void wined3d_volume_load_location(struct wined3d_volume *volume, + if (!volume->resource.heap_memory) + ERR("Trying to load WINED3D_LOCATION_SYSMEM without setting it up first.\n"); + +- if (volume->locations & WINED3D_LOCATION_DISCARDED) ++ if (volume->resource.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)) ++ else if (volume->resource.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) ++ if (volume->resource.locations & WINED3D_LOCATION_TEXTURE_RGB) + wined3d_texture_bind_and_dirtify(volume->container, context, FALSE); + else + wined3d_texture_bind_and_dirtify(volume->container, context, TRUE); +@@ -301,7 +301,7 @@ static void wined3d_volume_load_location(struct wined3d_volume *volume, + else + { + FIXME("Implement WINED3D_LOCATION_SYSMEM loading from %s.\n", +- wined3d_debug_location(volume->locations)); ++ wined3d_debug_location(volume->resource.locations)); + return; + } + wined3d_volume_validate_location(volume, WINED3D_LOCATION_SYSMEM); +@@ -311,16 +311,16 @@ static void wined3d_volume_load_location(struct wined3d_volume *volume, + if (!volume->pbo) + ERR("Trying to load WINED3D_LOCATION_BUFFER without setting it up first.\n"); + +- if (volume->locations & WINED3D_LOCATION_DISCARDED) ++ if (volume->resource.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)) ++ else if (volume->resource.locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) + { + struct wined3d_bo_address data = {volume->pbo, NULL}; + +- if (volume->locations & WINED3D_LOCATION_TEXTURE_RGB) ++ if (volume->resource.locations & WINED3D_LOCATION_TEXTURE_RGB) + wined3d_texture_bind_and_dirtify(volume->container, context, FALSE); + else + wined3d_texture_bind_and_dirtify(volume->container, context, TRUE); +@@ -330,7 +330,7 @@ static void wined3d_volume_load_location(struct wined3d_volume *volume, + else + { + FIXME("Implement WINED3D_LOCATION_BUFFER loading from %s.\n", +- wined3d_debug_location(volume->locations)); ++ wined3d_debug_location(volume->resource.locations)); + return; + } + wined3d_volume_validate_location(volume, WINED3D_LOCATION_BUFFER); +@@ -338,7 +338,7 @@ static void wined3d_volume_load_location(struct wined3d_volume *volume, + + default: + FIXME("Implement %s loading from %s.\n", wined3d_debug_location(location), +- wined3d_debug_location(volume->locations)); ++ wined3d_debug_location(volume->resource.locations)); + } + } + +@@ -595,7 +595,7 @@ HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume, + { + wined3d_volume_validate_location(volume, WINED3D_LOCATION_SYSMEM); + } +- else if (!(volume->locations & WINED3D_LOCATION_SYSMEM)) ++ else if (!(volume->resource.locations & WINED3D_LOCATION_SYSMEM)) + { + context = context_acquire(device, NULL); + wined3d_volume_load_location(volume, context, WINED3D_LOCATION_SYSMEM); +@@ -743,7 +743,7 @@ static HRESULT volume_init(struct wined3d_volume *volume, struct wined3d_texture + } + + volume->texture_level = level; +- volume->locations = WINED3D_LOCATION_DISCARDED; ++ volume->resource.locations = WINED3D_LOCATION_DISCARDED; + + if (desc->pool == WINED3D_POOL_DEFAULT && desc->usage & WINED3DUSAGE_DYNAMIC + && gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index f24808b..57a048f 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -5,7 +5,7 @@ + * Copyright 2002-2003 Raphael Junqueira + * Copyright 2002-2003, 2004 Jason Edmeades + * Copyright 2005 Oliver Stieber +- * Copyright 2006-2011, 2013 Stefan Dösinger for CodeWeavers ++ * Copyright 2006-2011, 2013-2014 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 +@@ -2082,6 +2082,7 @@ struct wined3d_resource + void *heap_memory; + UINT custom_row_pitch, custom_slice_pitch; + struct list resource_list_entry; ++ DWORD locations; + + void *parent; + const struct wined3d_parent_ops *parent_ops; +@@ -2236,7 +2237,7 @@ struct wined3d_volume + struct wined3d_resource resource; + struct wined3d_texture *container; + +- DWORD flags, locations; ++ DWORD flags; + GLint texture_level; + DWORD download_count; + GLuint pbo; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0010-wined3d-Move-validate_location-to-resource.c.patch b/patches/wined3d-CSMT_Main/0010-wined3d-Move-validate_location-to-resource.c.patch new file mode 100644 index 00000000..33f09bf1 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0010-wined3d-Move-validate_location-to-resource.c.patch @@ -0,0 +1,116 @@ +From 8b7f33e2323fa2acac3722c3a8a753b7a8f11db2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 3 Oct 2013 12:34:13 +0200 +Subject: wined3d: Move validate_location to resource.c. + +--- + dlls/wined3d/resource.c | 7 +++++++ + dlls/wined3d/volume.c | 19 ++++++------------- + dlls/wined3d/wined3d_private.h | 1 + + 3 files changed, 14 insertions(+), 13 deletions(-) + +diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c +index 8032a4c..bac15c0 100644 +--- a/dlls/wined3d/resource.c ++++ b/dlls/wined3d/resource.c +@@ -332,6 +332,13 @@ void wined3d_resource_update_draw_binding(struct wined3d_resource *resource) + resource->draw_binding = WINED3D_LOCATION_TEXTURE_RGB; + } + ++void wined3d_resource_validate_location(struct wined3d_resource *resource, DWORD location) ++{ ++ TRACE("Resource %p, setting %s.\n", resource, wined3d_debug_location(location)); ++ resource->locations |= location; ++ TRACE("new location flags are %s.\n", wined3d_debug_location(resource->locations)); ++} ++ + void CDECL wined3d_resource_get_pitch(const struct wined3d_resource *resource, UINT *row_pitch, + UINT *slice_pitch) + { +diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c +index ea56b38..6bc2724 100644 +--- a/dlls/wined3d/volume.c ++++ b/dlls/wined3d/volume.c +@@ -98,13 +98,6 @@ void wined3d_volume_upload_data(struct wined3d_volume *volume, const struct wine + HeapFree(GetProcessHeap(), 0, mem); + } + +-static void wined3d_volume_validate_location(struct wined3d_volume *volume, DWORD location) +-{ +- TRACE("Volume %p, setting %s.\n", volume, wined3d_debug_location(location)); +- volume->resource.locations |= location; +- TRACE("new location flags are %s.\n", wined3d_debug_location(volume->resource.locations)); +-} +- + void wined3d_volume_invalidate_location(struct wined3d_volume *volume, DWORD location) + { + TRACE("Volume %p, clearing %s.\n", volume, wined3d_debug_location(location)); +@@ -270,7 +263,7 @@ static void wined3d_volume_load_location(struct wined3d_volume *volume, + FIXME("Implement texture loading from %s.\n", wined3d_debug_location(volume->resource.locations)); + return; + } +- wined3d_volume_validate_location(volume, location); ++ wined3d_resource_validate_location(&volume->resource, location); + + if (wined3d_volume_can_evict(volume)) + wined3d_volume_evict_sysmem(volume); +@@ -304,7 +297,7 @@ static void wined3d_volume_load_location(struct wined3d_volume *volume, + wined3d_debug_location(volume->resource.locations)); + return; + } +- wined3d_volume_validate_location(volume, WINED3D_LOCATION_SYSMEM); ++ wined3d_resource_validate_location(&volume->resource, WINED3D_LOCATION_SYSMEM); + break; + + case WINED3D_LOCATION_BUFFER: +@@ -333,7 +326,7 @@ static void wined3d_volume_load_location(struct wined3d_volume *volume, + wined3d_debug_location(volume->resource.locations)); + return; + } +- wined3d_volume_validate_location(volume, WINED3D_LOCATION_BUFFER); ++ wined3d_resource_validate_location(&volume->resource, WINED3D_LOCATION_BUFFER); + break; + + default: +@@ -412,7 +405,7 @@ static void volume_unload(struct wined3d_resource *resource) + else + { + ERR("Out of memory when unloading volume %p.\n", volume); +- wined3d_volume_validate_location(volume, WINED3D_LOCATION_DISCARDED); ++ wined3d_resource_validate_location(&volume->resource, WINED3D_LOCATION_DISCARDED); + wined3d_volume_invalidate_location(volume, ~WINED3D_LOCATION_DISCARDED); + } + +@@ -558,7 +551,7 @@ HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume, + + wined3d_volume_prepare_pbo(volume, context); + if (flags & WINED3D_MAP_DISCARD) +- wined3d_volume_validate_location(volume, WINED3D_LOCATION_BUFFER); ++ wined3d_resource_validate_location(&volume->resource, WINED3D_LOCATION_BUFFER); + else + wined3d_volume_load_location(volume, context, WINED3D_LOCATION_BUFFER); + +@@ -593,7 +586,7 @@ HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume, + + if (flags & WINED3D_MAP_DISCARD) + { +- wined3d_volume_validate_location(volume, WINED3D_LOCATION_SYSMEM); ++ wined3d_resource_validate_location(&volume->resource, WINED3D_LOCATION_SYSMEM); + } + else if (!(volume->resource.locations & WINED3D_LOCATION_SYSMEM)) + { +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 57a048f..0c698b6 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2114,6 +2114,7 @@ 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; ++void wined3d_resource_validate_location(struct wined3d_resource *resource, DWORD location) DECLSPEC_HIDDEN; + + /* Tests show that the start address of resources is 32 byte aligned */ + #define RESOURCE_ALIGNMENT 16 +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0011-wined3d-Move-surface-locations-into-the-resource.patch b/patches/wined3d-CSMT_Main/0011-wined3d-Move-surface-locations-into-the-resource.patch new file mode 100644 index 00000000..691eac11 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0011-wined3d-Move-surface-locations-into-the-resource.patch @@ -0,0 +1,457 @@ +From 298ba6d476f8f76000f879b2ca61ff1fd0e810ff Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Tue, 21 Jan 2014 12:22:30 +0100 +Subject: wined3d: Move surface locations into the resource. + +--- + dlls/wined3d/arb_program_shader.c | 2 +- + dlls/wined3d/device.c | 4 +- + dlls/wined3d/drawprim.c | 2 +- + dlls/wined3d/surface.c | 99 ++++++++++++++++++++------------------- + dlls/wined3d/swapchain.c | 4 +- + dlls/wined3d/wined3d_private.h | 1 - + 6 files changed, 56 insertions(+), 56 deletions(-) + +diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c +index bc66c4a..c1b3b6d 100644 +--- a/dlls/wined3d/arb_program_shader.c ++++ b/dlls/wined3d/arb_program_shader.c +@@ -7649,7 +7649,7 @@ HRESULT arbfp_blit_surface(struct wined3d_device *device, DWORD filter, + + /* Now load the surface */ + if (wined3d_settings.offscreen_rendering_mode != ORM_FBO +- && (src_surface->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_DRAWABLE)) ++ && (src_surface->resource.locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_DRAWABLE)) + == WINED3D_LOCATION_DRAWABLE + && !wined3d_resource_is_offscreen(&src_surface->container->resource)) + { +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index 0b4c6f9..01ccd9d 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -236,7 +236,7 @@ static void prepare_ds_clear(struct wined3d_surface *ds, struct wined3d_context + { + RECT current_rect, r; + +- if (ds->locations & WINED3D_LOCATION_DISCARDED) ++ if (ds->resource.locations & WINED3D_LOCATION_DISCARDED) + { + /* Depth buffer was discarded, make it entirely current in its new location since + * there is no other place where we would get data anyway. */ +@@ -244,7 +244,7 @@ static void prepare_ds_clear(struct wined3d_surface *ds, struct wined3d_context + return; + } + +- if (ds->locations & location) ++ if (ds->resource.locations & location) + SetRect(¤t_rect, 0, 0, + ds->ds_current_size.cx, + ds->ds_current_size.cy); +diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c +index 2d39a83..7034b25 100644 +--- a/dlls/wined3d/drawprim.c ++++ b/dlls/wined3d/drawprim.c +@@ -648,7 +648,7 @@ void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_co + if (!context->render_offscreen && ds != device->onscreen_depth_stencil) + device_switch_onscreen_ds(device, context, ds); + +- if (ds->locations & location) ++ if (ds->resource.locations & location) + SetRect(¤t_rect, 0, 0, ds->ds_current_size.cx, ds->ds_current_size.cy); + else + SetRectEmpty(¤t_rect); +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 8a14169..c44179f 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -556,7 +556,7 @@ static void surface_prepare_system_memory(struct wined3d_surface *surface) + if (!wined3d_resource_allocate_sysmem(&surface->resource)) + ERR("Failed to allocate system memory.\n"); + +- if (surface->locations & WINED3D_LOCATION_SYSMEM) ++ if (surface->resource.locations & WINED3D_LOCATION_SYSMEM) + ERR("Surface without system memory has WINED3D_LOCATION_SYSMEM set.\n"); + } + +@@ -706,7 +706,7 @@ static HRESULT surface_private_setup(struct wined3d_surface *surface) + } + + if (surface->resource.usage & WINED3DUSAGE_DEPTHSTENCIL) +- surface->locations = WINED3D_LOCATION_DISCARDED; ++ surface->resource.locations = WINED3D_LOCATION_DISCARDED; + + if (surface_use_pbo(surface)) + surface->resource.map_binding = WINED3D_LOCATION_BUFFER; +@@ -746,7 +746,7 @@ static void surface_unmap(struct wined3d_surface *surface) + ERR("Unexpected map binding %s.\n", wined3d_debug_location(surface->resource.map_binding)); + } + +- if (surface->locations & (WINED3D_LOCATION_DRAWABLE | WINED3D_LOCATION_TEXTURE_RGB)) ++ if (surface->resource.locations & (WINED3D_LOCATION_DRAWABLE | WINED3D_LOCATION_TEXTURE_RGB)) + { + TRACE("Not dirtified, nothing to do.\n"); + return; +@@ -1726,7 +1726,7 @@ HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface, const P + surface_load_location(dst_surface, context, WINED3D_LOCATION_TEXTURE_RGB); + wined3d_texture_bind(dst_surface->container, context, FALSE); + +- surface_get_memory(src_surface, &data, src_surface->locations); ++ surface_get_memory(src_surface, &data, src_surface->resource.locations); + wined3d_resource_get_pitch(&src_surface->resource, &src_row_pitch, &src_slice_pitch); + + surface_upload_data(dst_surface, gl_info, src_format, src_rect, src_row_pitch, dst_point, FALSE, &data); +@@ -1872,7 +1872,7 @@ void surface_load(struct wined3d_surface *surface, struct wined3d_context *conte + if (ck_changed) + wined3d_texture_force_reload(surface->container); + } +- else if (!(surface->locations & location)) ++ else if (!(surface->resource.locations & location)) + { + TRACE("Reloading because surface is dirty.\n"); + } +@@ -2186,7 +2186,7 @@ HRESULT wined3d_surface_update_desc(struct wined3d_surface *surface, + create_dib = TRUE; + } + +- surface->locations = 0; ++ surface->resource.locations = 0; + wined3d_resource_free_sysmem(&surface->resource); + + width = texture_resource->width; +@@ -3088,9 +3088,9 @@ void flip_surface(struct wined3d_surface *front, struct wined3d_surface *back) + back->flags = front->flags; + front->flags = tmp_flags; + +- tmp_flags = back->locations; +- back->locations = front->locations; +- front->locations = tmp_flags; ++ tmp_flags = back->resource.locations; ++ back->resource.locations = front->resource.locations; ++ front->resource.locations = tmp_flags; + } + } + +@@ -3269,7 +3269,7 @@ static void fb_copy_to_texture_hwstretch(struct wined3d_surface *dst_surface, st + checkGLcall("glEnable(texture_target)"); + + /* For now invalidate the texture copy of the back buffer. Drawable and sysmem copy are untouched */ +- src_surface->locations &= ~WINED3D_LOCATION_TEXTURE_RGB; ++ src_surface->resource.locations &= ~WINED3D_LOCATION_TEXTURE_RGB; + } + + /* Make sure that the top pixel is always above the bottom pixel, and keep a separate upside down flag +@@ -3863,13 +3863,14 @@ void surface_modify_ds_location(struct wined3d_surface *surface, + { + TRACE("surface %p, new location %#x, w %u, h %u.\n", surface, location, w, h); + +- if (((surface->locations & WINED3D_LOCATION_TEXTURE_RGB) && !(location & WINED3D_LOCATION_TEXTURE_RGB)) +- || (!(surface->locations & WINED3D_LOCATION_TEXTURE_RGB) && (location & WINED3D_LOCATION_TEXTURE_RGB))) ++ if (((surface->resource.locations & WINED3D_LOCATION_TEXTURE_RGB) && !(location & WINED3D_LOCATION_TEXTURE_RGB)) ++ || (!(surface->resource.locations & WINED3D_LOCATION_TEXTURE_RGB) ++ && (location & WINED3D_LOCATION_TEXTURE_RGB))) + wined3d_texture_set_dirty(surface->container); + + surface->ds_current_size.cx = w; + surface->ds_current_size.cy = h; +- surface->locations = location; ++ surface->resource.locations = location; + } + + /* Context activation is done by the caller. */ +@@ -3884,7 +3885,7 @@ void surface_load_ds_location(struct wined3d_surface *surface, struct wined3d_co + /* TODO: Make this work for modes other than FBO */ + if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) return; + +- if (!(surface->locations & location)) ++ if (!(surface->resource.locations & location)) + { + w = surface->ds_current_size.cx; + h = surface->ds_current_size.cy; +@@ -3910,7 +3911,7 @@ void surface_load_ds_location(struct wined3d_surface *surface, struct wined3d_co + return; + } + +- if (surface->locations & WINED3D_LOCATION_DISCARDED) ++ if (surface->resource.locations & WINED3D_LOCATION_DISCARDED) + { + TRACE("Surface was discarded, no need copy data.\n"); + switch (location) +@@ -3927,17 +3928,17 @@ void surface_load_ds_location(struct wined3d_surface *surface, struct wined3d_co + default: + FIXME("Unhandled location %#x\n", location); + } +- surface->locations &= ~WINED3D_LOCATION_DISCARDED; +- surface->locations |= location; ++ surface->resource.locations &= ~WINED3D_LOCATION_DISCARDED; ++ surface->resource.locations |= location; + surface->ds_current_size.cx = surface->resource.width; + surface->ds_current_size.cy = surface->resource.height; + return; + } + +- if (!surface->locations) ++ if (!surface->resource.locations) + { + FIXME("No up to date depth stencil location.\n"); +- surface->locations |= location; ++ surface->resource.locations |= location; + surface->ds_current_size.cx = surface->resource.width; + surface->ds_current_size.cy = surface->resource.height; + return; +@@ -4026,7 +4027,7 @@ void surface_load_ds_location(struct wined3d_surface *surface, struct wined3d_co + ERR("Invalid location (%#x) specified.\n", location); + } + +- surface->locations |= location; ++ surface->resource.locations |= location; + surface->ds_current_size.cx = surface->resource.width; + surface->ds_current_size.cy = surface->resource.height; + } +@@ -4035,7 +4036,7 @@ void surface_validate_location(struct wined3d_surface *surface, DWORD location) + { + TRACE("surface %p, location %s.\n", surface, wined3d_debug_location(location)); + +- surface->locations |= location; ++ surface->resource.locations |= location; + } + + void surface_invalidate_location(struct wined3d_surface *surface, DWORD location) +@@ -4044,9 +4045,9 @@ void surface_invalidate_location(struct wined3d_surface *surface, DWORD location + + if (location & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) + wined3d_texture_set_dirty(surface->container); +- surface->locations &= ~location; ++ surface->resource.locations &= ~location; + +- if (!surface->locations) ++ if (!surface->resource.locations) + ERR("Surface %p does not have any up to date location.\n", surface); + } + +@@ -4082,7 +4083,7 @@ static void surface_copy_simple_location(struct wined3d_surface *surface, DWORD + UINT size = surface->resource.size; + + surface_get_memory(surface, &dst, location); +- surface_get_memory(surface, &src, surface->locations); ++ surface_get_memory(surface, &src, surface->resource.locations); + + if (dst.buffer_object) + { +@@ -4115,33 +4116,33 @@ static void surface_load_sysmem(struct wined3d_surface *surface, + { + const struct wined3d_gl_info *gl_info = context->gl_info; + +- if (surface->locations & surface_simple_locations) ++ if (surface->resource.locations & surface_simple_locations) + { + surface_copy_simple_location(surface, dst_location); + return; + } + +- if (surface->locations & (WINED3D_LOCATION_RB_MULTISAMPLE | WINED3D_LOCATION_RB_RESOLVED)) ++ if (surface->resource.locations & (WINED3D_LOCATION_RB_MULTISAMPLE | WINED3D_LOCATION_RB_RESOLVED)) + surface_load_location(surface, context, WINED3D_LOCATION_TEXTURE_RGB); + + /* Download the surface to system memory. */ +- if (surface->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) ++ if (surface->resource.locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) + { + wined3d_texture_bind_and_dirtify(surface->container, context, +- !(surface->locations & WINED3D_LOCATION_TEXTURE_RGB)); ++ !(surface->resource.locations & WINED3D_LOCATION_TEXTURE_RGB)); + surface_download_data(surface, gl_info, dst_location); + + return; + } + +- if (surface->locations & WINED3D_LOCATION_DRAWABLE) ++ if (surface->resource.locations & WINED3D_LOCATION_DRAWABLE) + { + read_from_framebuffer(surface, context, dst_location); + return; + } + + FIXME("Can't load surface %p with location flags %s into sysmem.\n", +- surface, wined3d_debug_location(surface->locations)); ++ surface, wined3d_debug_location(surface->resource.locations)); + } + + /* Context activation is done by the caller. */ +@@ -4181,14 +4182,14 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + + if (wined3d_settings.offscreen_rendering_mode != ORM_FBO + && wined3d_resource_is_offscreen(&texture->resource) +- && (surface->locations & WINED3D_LOCATION_DRAWABLE)) ++ && (surface->resource.locations & WINED3D_LOCATION_DRAWABLE)) + { + surface_load_fb_texture(surface, srgb); + + return WINED3D_OK; + } + +- if (surface->locations & (WINED3D_LOCATION_TEXTURE_SRGB | WINED3D_LOCATION_TEXTURE_RGB) ++ if (surface->resource.locations & (WINED3D_LOCATION_TEXTURE_SRGB | WINED3D_LOCATION_TEXTURE_RGB) + && (surface->resource.format->flags & WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB) + && fbo_blit_supported(gl_info, WINED3D_BLIT_OP_COLOR_BLIT, + NULL, surface->resource.usage, surface->resource.pool, surface->resource.format, +@@ -4204,13 +4205,13 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + return WINED3D_OK; + } + +- if (surface->locations & (WINED3D_LOCATION_RB_MULTISAMPLE | WINED3D_LOCATION_RB_RESOLVED) ++ if (surface->resource.locations & (WINED3D_LOCATION_RB_MULTISAMPLE | WINED3D_LOCATION_RB_RESOLVED) + && (!srgb || (surface->resource.format->flags & WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB)) + && fbo_blit_supported(gl_info, WINED3D_BLIT_OP_COLOR_BLIT, + NULL, surface->resource.usage, surface->resource.pool, surface->resource.format, + NULL, surface->resource.usage, surface->resource.pool, surface->resource.format)) + { +- DWORD src_location = surface->locations & WINED3D_LOCATION_RB_RESOLVED ? ++ DWORD src_location = surface->resource.locations & WINED3D_LOCATION_RB_RESOLVED ? + WINED3D_LOCATION_RB_RESOLVED : WINED3D_LOCATION_RB_MULTISAMPLE; + DWORD dst_location = srgb ? WINED3D_LOCATION_TEXTURE_SRGB : WINED3D_LOCATION_TEXTURE_RGB; + RECT rect = {0, 0, surface->resource.width, surface->resource.height}; +@@ -4225,7 +4226,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + + if (srgb) + { +- if ((surface->locations & (WINED3D_LOCATION_TEXTURE_RGB | surface->resource.map_binding)) ++ if ((surface->resource.locations & (WINED3D_LOCATION_TEXTURE_RGB | surface->resource.map_binding)) + == WINED3D_LOCATION_TEXTURE_RGB) + { + /* Performance warning... */ +@@ -4236,7 +4237,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + } + else + { +- if ((surface->locations & (WINED3D_LOCATION_TEXTURE_SRGB | surface->resource.map_binding)) ++ if ((surface->resource.locations & (WINED3D_LOCATION_TEXTURE_SRGB | surface->resource.map_binding)) + == WINED3D_LOCATION_TEXTURE_SRGB) + { + /* Performance warning... */ +@@ -4246,7 +4247,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + } + } + +- if (!(surface->locations & surface_simple_locations)) ++ if (!(surface->resource.locations & surface_simple_locations)) + { + WARN("Trying to load a texture from sysmem, but no simple location is valid.\n"); + /* Lets hope we get it from somewhere... */ +@@ -4288,7 +4289,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + surface_remove_pbo(surface, gl_info); + } + +- surface_get_memory(surface, &data, surface->locations); ++ surface_get_memory(surface, &data, surface->resource.locations); + if (format.convert) + { + /* This code is entered for texture formats which need a fixup. */ +@@ -4344,7 +4345,7 @@ static void surface_multisample_resolve(struct wined3d_surface *surface, struct + { + RECT rect = {0, 0, surface->resource.width, surface->resource.height}; + +- if (!(surface->locations & WINED3D_LOCATION_RB_MULTISAMPLE)) ++ if (!(surface->resource.locations & WINED3D_LOCATION_RB_MULTISAMPLE)) + ERR("Trying to resolve multisampled surface %p, but location WINED3D_LOCATION_RB_MULTISAMPLE not current.\n", + surface); + +@@ -4362,12 +4363,12 @@ void surface_load_location(struct wined3d_surface *surface, struct wined3d_conte + if (surface->resource.usage & WINED3DUSAGE_DEPTHSTENCIL) + { + if (location == WINED3D_LOCATION_TEXTURE_RGB +- && surface->locations & (WINED3D_LOCATION_DRAWABLE | WINED3D_LOCATION_DISCARDED)) ++ && surface->resource.locations & (WINED3D_LOCATION_DRAWABLE | WINED3D_LOCATION_DISCARDED)) + { + surface_load_ds_location(surface, context, location); + return; + } +- else if (location & surface->locations ++ else if (location & surface->resource.locations + && surface->container->resource.draw_binding != WINED3D_LOCATION_DRAWABLE) + { + /* Already up to date, nothing to do. */ +@@ -4376,12 +4377,12 @@ void surface_load_location(struct wined3d_surface *surface, struct wined3d_conte + else + { + FIXME("Unimplemented copy from %s to %s for depth/stencil buffers.\n", +- wined3d_debug_location(surface->locations), wined3d_debug_location(location)); ++ wined3d_debug_location(surface->resource.locations), wined3d_debug_location(location)); + return; + } + } + +- if (surface->locations & location) ++ if (surface->resource.locations & location) + { + TRACE("Location already up to date.\n"); + return; +@@ -4395,7 +4396,7 @@ void surface_load_location(struct wined3d_surface *surface, struct wined3d_conte + required_access, surface->resource.access_flags); + } + +- if (!surface->locations) ++ if (!surface->resource.locations) + { + ERR("Surface %p does not have any up to date location.\n", surface); + surface->flags |= SFLAG_LOST; +@@ -4434,7 +4435,7 @@ void surface_load_location(struct wined3d_surface *surface, struct wined3d_conte + + surface_validate_location(surface, location); + +- if (location != WINED3D_LOCATION_SYSMEM && (surface->locations & WINED3D_LOCATION_SYSMEM)) ++ if (location != WINED3D_LOCATION_SYSMEM && (surface->resource.locations & WINED3D_LOCATION_SYSMEM)) + surface_evict_sysmem(surface); + + return; +@@ -5439,8 +5440,8 @@ HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const REC + { + /* In principle this would apply to depth blits as well, but we don't + * implement those in the CPU blitter at the moment. */ +- if ((dst_surface->locations & dst_surface->resource.map_binding) +- && (!src_surface || (src_surface->locations & src_surface->resource.map_binding))) ++ if ((dst_surface->resource.locations & dst_surface->resource.map_binding) ++ && (!src_surface || (src_surface->resource.locations & src_surface->resource.map_binding))) + { + if (scale) + TRACE("Not doing sysmem blit because of scaling.\n"); +@@ -5467,8 +5468,8 @@ HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const REC + TRACE("Color blit.\n"); + + /* Upload */ +- if ((src_surface->locations & WINED3D_LOCATION_SYSMEM) +- && !(dst_surface->locations & WINED3D_LOCATION_SYSMEM)) ++ if ((src_surface->resource.locations & WINED3D_LOCATION_SYSMEM) ++ && !(dst_surface->resource.locations & WINED3D_LOCATION_SYSMEM)) + { + if (scale) + TRACE("Not doing upload because of scaling.\n"); +diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c +index d742b11..601d3ad 100644 +--- a/dlls/wined3d/swapchain.c ++++ b/dlls/wined3d/swapchain.c +@@ -555,8 +555,8 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT + } + + front = surface_from_resource(wined3d_texture_get_sub_resource(swapchain->front_buffer, 0)); +- if (!swapchain->render_to_fbo && ((front->locations & WINED3D_LOCATION_SYSMEM) +- || (back_buffer->locations & WINED3D_LOCATION_SYSMEM))) ++ if (!swapchain->render_to_fbo && ((front->resource.locations & WINED3D_LOCATION_SYSMEM) ++ || (back_buffer->resource.locations & WINED3D_LOCATION_SYSMEM))) + { + /* Both memory copies of the surfaces are ok, flip them around too instead of dirtifying + * Doesn't work with render_to_fbo because we're not flipping +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 0c698b6..4011833 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2297,7 +2297,6 @@ struct wined3d_surface + const struct wined3d_surface_ops *surface_ops; + struct wined3d_texture *container; + void *user_memory; +- DWORD locations; + + DWORD flags; + +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0012-wined3d-Remove-surface_validate_location.patch b/patches/wined3d-CSMT_Main/0012-wined3d-Remove-surface_validate_location.patch new file mode 100644 index 00000000..4692d564 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0012-wined3d-Remove-surface_validate_location.patch @@ -0,0 +1,217 @@ +From a15ccac8ee6ece2955548900f4e7b4a993a498b2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Sat, 4 Jan 2014 00:53:47 +0100 +Subject: wined3d: Remove surface_validate_location. + +--- + dlls/wined3d/arb_program_shader.c | 2 +- + dlls/wined3d/device.c | 2 +- + dlls/wined3d/surface.c | 29 +++++++++++------------------ + dlls/wined3d/swapchain.c | 12 ++++++------ + dlls/wined3d/wined3d_private.h | 1 - + 5 files changed, 19 insertions(+), 27 deletions(-) + +diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c +index c1b3b6d..08f92cb 100644 +--- a/dlls/wined3d/arb_program_shader.c ++++ b/dlls/wined3d/arb_program_shader.c +@@ -7686,7 +7686,7 @@ HRESULT arbfp_blit_surface(struct wined3d_device *device, DWORD filter, + + context_release(context); + +- surface_validate_location(dst_surface, dst_surface->container->resource.draw_binding); ++ wined3d_resource_validate_location(&dst_surface->resource, dst_surface->container->resource.draw_binding); + surface_invalidate_location(dst_surface, ~dst_surface->container->resource.draw_binding); + + return WINED3D_OK; +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index 01ccd9d..e10ea1c 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -392,7 +392,7 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c + + if (rt) + { +- surface_validate_location(rt, rt->container->resource.draw_binding); ++ wined3d_resource_validate_location(&rt->resource, rt->container->resource.draw_binding); + surface_invalidate_location(rt, ~rt->container->resource.draw_binding); + } + } +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index c44179f..b56796e 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -1224,7 +1224,7 @@ static void surface_unload(struct wined3d_resource *resource) + * and all flags get lost */ + surface_prepare_system_memory(surface); + memset(surface->resource.heap_memory, 0, surface->resource.size); +- surface_validate_location(surface, WINED3D_LOCATION_SYSMEM); ++ wined3d_resource_validate_location(&surface->resource, WINED3D_LOCATION_SYSMEM); + surface_invalidate_location(surface, ~WINED3D_LOCATION_SYSMEM); + + /* We also get here when the ddraw swapchain is destroyed, for example +@@ -1735,7 +1735,7 @@ HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface, const P + + context_release(context); + +- surface_validate_location(dst_surface, WINED3D_LOCATION_TEXTURE_RGB); ++ wined3d_resource_validate_location(&dst_surface->resource, WINED3D_LOCATION_TEXTURE_RGB); + surface_invalidate_location(dst_surface, ~WINED3D_LOCATION_TEXTURE_RGB); + + return WINED3D_OK; +@@ -2253,7 +2253,7 @@ HRESULT wined3d_surface_update_desc(struct wined3d_surface *surface, + valid_location = WINED3D_LOCATION_SYSMEM; + } + +- surface_validate_location(surface, valid_location); ++ wined3d_resource_validate_location(&surface->resource, valid_location); + + return WINED3D_OK; + } +@@ -2645,7 +2645,7 @@ HRESULT CDECL wined3d_surface_map(struct wined3d_surface *surface, + { + TRACE("WINED3D_MAP_DISCARD flag passed, marking %s as up to date.\n", + wined3d_debug_location(surface->resource.map_binding)); +- surface_validate_location(surface, surface->resource.map_binding); ++ wined3d_resource_validate_location(&surface->resource, surface->resource.map_binding); + } + else + { +@@ -3200,7 +3200,7 @@ static void fb_copy_to_texture_direct(struct wined3d_surface *dst_surface, struc + + /* The texture is now most up to date - If the surface is a render target + * and has a drawable, this path is never entered. */ +- surface_validate_location(dst_surface, WINED3D_LOCATION_TEXTURE_RGB); ++ wined3d_resource_validate_location(&dst_surface->resource, WINED3D_LOCATION_TEXTURE_RGB); + surface_invalidate_location(dst_surface, ~WINED3D_LOCATION_TEXTURE_RGB); + } + +@@ -3474,7 +3474,7 @@ static void fb_copy_to_texture_hwstretch(struct wined3d_surface *dst_surface, st + + /* The texture is now most up to date - If the surface is a render target + * and has a drawable, this path is never entered. */ +- surface_validate_location(dst_surface, WINED3D_LOCATION_TEXTURE_RGB); ++ wined3d_resource_validate_location(&dst_surface->resource, WINED3D_LOCATION_TEXTURE_RGB); + surface_invalidate_location(dst_surface, ~WINED3D_LOCATION_TEXTURE_RGB); + } + +@@ -3787,7 +3787,7 @@ static HRESULT surface_blt_special(struct wined3d_surface *dst_surface, const RE + wined3d_texture_set_color_key(src_surface->container, WINEDDSD_CKSRCBLT, + (old_color_key_flags & WINEDDSD_CKSRCBLT) ? &old_blt_key : NULL); + +- surface_validate_location(dst_surface, dst_surface->container->resource.draw_binding); ++ wined3d_resource_validate_location(&dst_surface->resource, dst_surface->container->resource.draw_binding); + surface_invalidate_location(dst_surface, ~dst_surface->container->resource.draw_binding); + + return WINED3D_OK; +@@ -4032,13 +4032,6 @@ void surface_load_ds_location(struct wined3d_surface *surface, struct wined3d_co + surface->ds_current_size.cy = surface->resource.height; + } + +-void surface_validate_location(struct wined3d_surface *surface, DWORD location) +-{ +- TRACE("surface %p, location %s.\n", surface, wined3d_debug_location(location)); +- +- surface->resource.locations |= location; +-} +- + void surface_invalidate_location(struct wined3d_surface *surface, DWORD location) + { + TRACE("surface %p, location %s.\n", surface, wined3d_debug_location(location)); +@@ -4433,7 +4426,7 @@ void surface_load_location(struct wined3d_surface *surface, struct wined3d_conte + break; + } + +- surface_validate_location(surface, location); ++ wined3d_resource_validate_location(&surface->resource, location); + + if (location != WINED3D_LOCATION_SYSMEM && (surface->resource.locations & WINED3D_LOCATION_SYSMEM)) + surface_evict_sysmem(surface); +@@ -5528,7 +5521,7 @@ HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const REC + dst_surface, dst_surface->container->resource.draw_binding, &dst_rect); + context_release(context); + +- surface_validate_location(dst_surface, dst_surface->container->resource.draw_binding); ++ wined3d_resource_validate_location(&dst_surface->resource, dst_surface->container->resource.draw_binding); + surface_invalidate_location(dst_surface, ~dst_surface->container->resource.draw_binding); + + return WINED3D_OK; +@@ -5625,7 +5618,7 @@ static HRESULT surface_init(struct wined3d_surface *surface, struct wined3d_text + } + + surface->container = container; +- surface_validate_location(surface, WINED3D_LOCATION_SYSMEM); ++ wined3d_resource_validate_location(&surface->resource, WINED3D_LOCATION_SYSMEM); + list_init(&surface->renderbuffers); + list_init(&surface->overlays); + +@@ -5657,7 +5650,7 @@ static HRESULT surface_init(struct wined3d_surface *surface, struct wined3d_text + if (surface->resource.map_binding == WINED3D_LOCATION_DIB) + { + wined3d_resource_free_sysmem(&surface->resource); +- surface_validate_location(surface, WINED3D_LOCATION_DIB); ++ wined3d_resource_validate_location(&surface->resource, WINED3D_LOCATION_DIB); + surface_invalidate_location(surface, WINED3D_LOCATION_SYSMEM); + } + +diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c +index 601d3ad..bdb4b67 100644 +--- a/dlls/wined3d/swapchain.c ++++ b/dlls/wined3d/swapchain.c +@@ -569,19 +569,19 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT + /* Tell the front buffer surface that is has been modified. However, + * the other locations were preserved during that, so keep the flags. + * This serves to update the emulated overlay, if any. */ +- surface_validate_location(front, WINED3D_LOCATION_DRAWABLE); ++ wined3d_resource_validate_location(&front->resource, WINED3D_LOCATION_DRAWABLE); + } + else + { +- surface_validate_location(front, WINED3D_LOCATION_DRAWABLE); ++ wined3d_resource_validate_location(&front->resource, WINED3D_LOCATION_DRAWABLE); + surface_invalidate_location(front, ~WINED3D_LOCATION_DRAWABLE); +- surface_validate_location(back_buffer, WINED3D_LOCATION_DRAWABLE); ++ wined3d_resource_validate_location(&back_buffer->resource, WINED3D_LOCATION_DRAWABLE); + surface_invalidate_location(back_buffer, ~WINED3D_LOCATION_DRAWABLE); + } + } + else + { +- surface_validate_location(front, WINED3D_LOCATION_DRAWABLE); ++ wined3d_resource_validate_location(&front->resource, 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. +@@ -590,7 +590,7 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT + */ + if (swapchain->desc.swap_effect == WINED3D_SWAP_EFFECT_FLIP) + { +- surface_validate_location(back_buffer, back_buffer->container->resource.draw_binding); ++ wined3d_resource_validate_location(&back_buffer->resource, back_buffer->container->resource.draw_binding); + surface_invalidate_location(back_buffer, ~back_buffer->container->resource.draw_binding); + } + } +@@ -865,7 +865,7 @@ static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3 + wined3d_texture_set_swapchain(swapchain->front_buffer, swapchain); + if (!(device->wined3d->flags & WINED3D_NO3D)) + { +- surface_validate_location(front_buffer, WINED3D_LOCATION_DRAWABLE); ++ wined3d_resource_validate_location(&front_buffer->resource, WINED3D_LOCATION_DRAWABLE); + surface_invalidate_location(front_buffer, ~WINED3D_LOCATION_DRAWABLE); + } + +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 4011833..5ca3ab8 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2368,7 +2368,6 @@ HRESULT wined3d_surface_update_desc(struct wined3d_surface *surface, + 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; +-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; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0013-wined3d-Move-invalidate_location-to-resource.c.patch b/patches/wined3d-CSMT_Main/0013-wined3d-Move-invalidate_location-to-resource.c.patch new file mode 100644 index 00000000..1088f96c --- /dev/null +++ b/patches/wined3d-CSMT_Main/0013-wined3d-Move-invalidate_location-to-resource.c.patch @@ -0,0 +1,161 @@ +From c7669f4cc8e98c81027cd1c2392d3435ec534206 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 3 Oct 2013 12:36:46 +0200 +Subject: wined3d: Move invalidate_location to resource.c. + +--- + dlls/wined3d/device.c | 2 +- + dlls/wined3d/resource.c | 7 +++++++ + dlls/wined3d/texture.c | 4 +--- + dlls/wined3d/volume.c | 21 +++++++-------------- + dlls/wined3d/wined3d_private.h | 2 +- + 5 files changed, 17 insertions(+), 19 deletions(-) + +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index e10ea1c..600afed 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -3487,7 +3487,7 @@ static HRESULT device_update_volume(struct wined3d_device *device, + data.buffer_object = 0; + data.addr = src.data; + wined3d_volume_upload_data(dst_volume, context, &data); +- wined3d_volume_invalidate_location(dst_volume, ~WINED3D_LOCATION_TEXTURE_RGB); ++ wined3d_resource_invalidate_location(&dst_volume->resource, ~WINED3D_LOCATION_TEXTURE_RGB); + + context_release(context); + +diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c +index bac15c0..1ec27d3 100644 +--- a/dlls/wined3d/resource.c ++++ b/dlls/wined3d/resource.c +@@ -339,6 +339,13 @@ void wined3d_resource_validate_location(struct wined3d_resource *resource, DWORD + TRACE("new location flags are %s.\n", wined3d_debug_location(resource->locations)); + } + ++void wined3d_resource_invalidate_location(struct wined3d_resource *resource, DWORD location) ++{ ++ TRACE("Resource %p, setting %s.\n", resource, wined3d_debug_location(location)); ++ resource->locations &= ~location; ++ TRACE("new location flags are %s.\n", wined3d_debug_location(resource->locations)); ++} ++ + void CDECL wined3d_resource_get_pitch(const struct wined3d_resource *resource, UINT *row_pitch, + UINT *slice_pitch) + { +diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c +index c173518..f003fa2 100644 +--- a/dlls/wined3d/texture.c ++++ b/dlls/wined3d/texture.c +@@ -1286,9 +1286,7 @@ static void texture3d_sub_resource_cleanup(struct wined3d_resource *sub_resource + + static void texture3d_sub_resource_invalidate_location(struct wined3d_resource *sub_resource, DWORD location) + { +- struct wined3d_volume *volume = volume_from_resource(sub_resource); +- +- wined3d_volume_invalidate_location(volume, location); ++ wined3d_resource_invalidate_location(sub_resource, location); + } + + static void texture3d_prepare_texture(struct wined3d_texture *texture, struct wined3d_context *context, BOOL srgb) +diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c +index 6bc2724..3b742d2 100644 +--- a/dlls/wined3d/volume.c ++++ b/dlls/wined3d/volume.c +@@ -98,13 +98,6 @@ void wined3d_volume_upload_data(struct wined3d_volume *volume, const struct wine + HeapFree(GetProcessHeap(), 0, mem); + } + +-void wined3d_volume_invalidate_location(struct wined3d_volume *volume, DWORD location) +-{ +- TRACE("Volume %p, clearing %s.\n", volume, wined3d_debug_location(location)); +- volume->resource.locations &= ~location; +- TRACE("new location flags are %s.\n", wined3d_debug_location(volume->resource.locations)); +-} +- + /* 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) +@@ -140,7 +133,7 @@ static void wined3d_volume_download_data(struct wined3d_volume *volume, + static void wined3d_volume_evict_sysmem(struct wined3d_volume *volume) + { + wined3d_resource_free_sysmem(&volume->resource); +- wined3d_volume_invalidate_location(volume, WINED3D_LOCATION_SYSMEM); ++ wined3d_resource_invalidate_location(&volume->resource, WINED3D_LOCATION_SYSMEM); + } + + static DWORD volume_access_from_location(DWORD location) +@@ -238,7 +231,7 @@ static void wined3d_volume_load_location(struct wined3d_volume *volume, + if (volume->resource.locations & WINED3D_LOCATION_DISCARDED) + { + TRACE("Volume previously discarded, nothing to do.\n"); +- wined3d_volume_invalidate_location(volume, WINED3D_LOCATION_DISCARDED); ++ wined3d_resource_invalidate_location(&volume->resource, WINED3D_LOCATION_DISCARDED); + } + else if (volume->resource.locations & WINED3D_LOCATION_SYSMEM) + { +@@ -277,7 +270,7 @@ static void wined3d_volume_load_location(struct wined3d_volume *volume, + if (volume->resource.locations & WINED3D_LOCATION_DISCARDED) + { + TRACE("Volume previously discarded, nothing to do.\n"); +- wined3d_volume_invalidate_location(volume, WINED3D_LOCATION_DISCARDED); ++ wined3d_resource_invalidate_location(&volume->resource, WINED3D_LOCATION_DISCARDED); + } + else if (volume->resource.locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) + { +@@ -307,7 +300,7 @@ static void wined3d_volume_load_location(struct wined3d_volume *volume, + if (volume->resource.locations & WINED3D_LOCATION_DISCARDED) + { + TRACE("Volume previously discarded, nothing to do.\n"); +- wined3d_volume_invalidate_location(volume, WINED3D_LOCATION_DISCARDED); ++ wined3d_resource_invalidate_location(&volume->resource, WINED3D_LOCATION_DISCARDED); + } + else if (volume->resource.locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) + { +@@ -400,13 +393,13 @@ static void volume_unload(struct wined3d_resource *resource) + 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); ++ wined3d_resource_invalidate_location(&volume->resource, ~WINED3D_LOCATION_SYSMEM); + } + else + { + ERR("Out of memory when unloading volume %p.\n", volume); + wined3d_resource_validate_location(&volume->resource, WINED3D_LOCATION_DISCARDED); +- wined3d_volume_invalidate_location(volume, ~WINED3D_LOCATION_DISCARDED); ++ wined3d_resource_invalidate_location(&volume->resource, ~WINED3D_LOCATION_DISCARDED); + } + + if (volume->pbo) +@@ -640,7 +633,7 @@ HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume, + 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); ++ wined3d_resource_invalidate_location(&volume->resource, ~volume->resource.map_binding); + } + + volume->resource.map_count++; +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 5ca3ab8..fd28fa5 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2115,6 +2115,7 @@ BOOL wined3d_resource_is_offscreen(struct wined3d_resource *resource) DECLSPEC_H + 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; + void wined3d_resource_validate_location(struct wined3d_resource *resource, DWORD location) DECLSPEC_HIDDEN; ++void wined3d_resource_invalidate_location(struct wined3d_resource *resource, DWORD location) DECLSPEC_HIDDEN; + + /* Tests show that the start address of resources is 32 byte aligned */ + #define RESOURCE_ALIGNMENT 16 +@@ -2255,7 +2256,6 @@ HRESULT wined3d_volume_create(struct wined3d_texture *container, const struct wi + void wined3d_volume_destroy(struct wined3d_volume *volume) 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; + void wined3d_volume_upload_data(struct wined3d_volume *volume, const struct wined3d_context *context, + const struct wined3d_bo_address *data) DECLSPEC_HIDDEN; + +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0014-wined3d-Invalidate-containers-via-callback.patch b/patches/wined3d-CSMT_Main/0014-wined3d-Invalidate-containers-via-callback.patch new file mode 100644 index 00000000..19fb1a2f --- /dev/null +++ b/patches/wined3d-CSMT_Main/0014-wined3d-Invalidate-containers-via-callback.patch @@ -0,0 +1,144 @@ +From 39c0dd79f403ac4aac1cf660e207b0ed2703e81b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Sun, 17 Nov 2013 18:44:48 +0100 +Subject: wined3d: Invalidate containers via callback. + +--- + dlls/wined3d/buffer.c | 6 ++++++ + dlls/wined3d/resource.c | 2 ++ + dlls/wined3d/surface.c | 6 ++++++ + dlls/wined3d/texture.c | 6 ++++++ + dlls/wined3d/volume.c | 12 +++++++++--- + dlls/wined3d/wined3d_private.h | 1 + + 6 files changed, 30 insertions(+), 3 deletions(-) + +diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c +index 989026f..d9bc820 100644 +--- a/dlls/wined3d/buffer.c ++++ b/dlls/wined3d/buffer.c +@@ -1123,11 +1123,17 @@ static ULONG buffer_resource_decref(struct wined3d_resource *resource) + return wined3d_buffer_decref(buffer_from_resource(resource)); + } + ++static void wined3d_buffer_location_invalidated(struct wined3d_resource *resource, DWORD location) ++{ ++ ERR("Not yet implemented.\n"); ++} ++ + static const struct wined3d_resource_ops buffer_resource_ops = + { + buffer_resource_incref, + buffer_resource_decref, + buffer_unload, ++ wined3d_buffer_location_invalidated, + }; + + static HRESULT buffer_init(struct wined3d_buffer *buffer, struct wined3d_device *device, +diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c +index 1ec27d3..9d2db2b 100644 +--- a/dlls/wined3d/resource.c ++++ b/dlls/wined3d/resource.c +@@ -344,6 +344,8 @@ void wined3d_resource_invalidate_location(struct wined3d_resource *resource, DWO + TRACE("Resource %p, setting %s.\n", resource, wined3d_debug_location(location)); + resource->locations &= ~location; + TRACE("new location flags are %s.\n", wined3d_debug_location(resource->locations)); ++ ++ resource->resource_ops->resource_location_invalidated(resource, location); + } + + void CDECL wined3d_resource_get_pitch(const struct wined3d_resource *resource, UINT *row_pitch, +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index b56796e..6c2698a 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -1273,11 +1273,17 @@ static void surface_unload(struct wined3d_resource *resource) + resource_unload(resource); + } + ++static void wined3d_surface_location_invalidated(struct wined3d_resource *resource, DWORD location) ++{ ++ ERR("Not yet implemented.\n"); ++} ++ + static const struct wined3d_resource_ops surface_resource_ops = + { + surface_resource_incref, + surface_resource_decref, + surface_unload, ++ wined3d_surface_location_invalidated, + }; + + static const struct wined3d_surface_ops surface_ops = +diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c +index f003fa2..c42e475 100644 +--- a/dlls/wined3d/texture.c ++++ b/dlls/wined3d/texture.c +@@ -986,11 +986,17 @@ static void wined3d_texture_unload(struct wined3d_resource *resource) + wined3d_texture_unload_gl_texture(texture); + } + ++static void wined3d_texture_load_location_invalidated(struct wined3d_resource *resource, DWORD location) ++{ ++ ERR("Should not be called on textures.\n"); ++} ++ + static const struct wined3d_resource_ops texture_resource_ops = + { + texture_resource_incref, + texture_resource_decref, + wined3d_texture_unload, ++ wined3d_texture_load_location_invalidated, + }; + + static HRESULT cubetexture_init(struct wined3d_texture *texture, const struct wined3d_resource_desc *desc, +diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c +index 3b742d2..6921b87 100644 +--- a/dlls/wined3d/volume.c ++++ b/dlls/wined3d/volume.c +@@ -631,10 +631,7 @@ HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume, + } + + if (!(flags & (WINED3D_MAP_NO_DIRTY_UPDATE | WINED3D_MAP_READONLY))) +- { +- wined3d_texture_set_dirty(volume->container); + wined3d_resource_invalidate_location(&volume->resource, ~volume->resource.map_binding); +- } + + volume->resource.map_count++; + +@@ -688,11 +685,20 @@ static ULONG volume_resource_decref(struct wined3d_resource *resource) + return wined3d_volume_decref(volume_from_resource(resource)); + } + ++static void wined3d_volume_location_invalidated(struct wined3d_resource *resource, DWORD location) ++{ ++ struct wined3d_volume *volume = volume_from_resource(resource); ++ ++ if (location & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) ++ wined3d_texture_set_dirty(volume->container); ++} ++ + static const struct wined3d_resource_ops volume_resource_ops = + { + volume_resource_incref, + volume_resource_decref, + volume_unload, ++ wined3d_volume_location_invalidated, + }; + + static HRESULT volume_init(struct wined3d_volume *volume, struct wined3d_texture *container, +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index fd28fa5..60d1b56 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2057,6 +2057,7 @@ struct wined3d_resource_ops + ULONG (*resource_incref)(struct wined3d_resource *resource); + ULONG (*resource_decref)(struct wined3d_resource *resource); + void (*resource_unload)(struct wined3d_resource *resource); ++ void (*resource_location_invalidated)(struct wined3d_resource *resource, DWORD location); + }; + + struct wined3d_resource +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0015-wined3d-Remove-surface_invalidate_location.patch b/patches/wined3d-CSMT_Main/0015-wined3d-Remove-surface_invalidate_location.patch new file mode 100644 index 00000000..cbef2d37 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0015-wined3d-Remove-surface_invalidate_location.patch @@ -0,0 +1,327 @@ +From 421ef7716a0748076fd14bb607849f81ab149679 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Sat, 4 Jan 2014 01:02:15 +0100 +Subject: wined3d: Remove surface_invalidate_location. + +--- + dlls/wined3d/arb_program_shader.c | 2 +- + dlls/wined3d/context.c | 2 +- + dlls/wined3d/device.c | 2 +- + dlls/wined3d/drawprim.c | 2 +- + dlls/wined3d/surface.c | 47 ++++++++++++++++----------------------- + dlls/wined3d/swapchain.c | 12 +++++----- + dlls/wined3d/texture.c | 6 ++--- + dlls/wined3d/wined3d_private.h | 1 - + 8 files changed, 31 insertions(+), 43 deletions(-) + +diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c +index 08f92cb..f612099 100644 +--- a/dlls/wined3d/arb_program_shader.c ++++ b/dlls/wined3d/arb_program_shader.c +@@ -7687,7 +7687,7 @@ HRESULT arbfp_blit_surface(struct wined3d_device *device, DWORD filter, + context_release(context); + + wined3d_resource_validate_location(&dst_surface->resource, dst_surface->container->resource.draw_binding); +- surface_invalidate_location(dst_surface, ~dst_surface->container->resource.draw_binding); ++ wined3d_resource_invalidate_location(&dst_surface->resource, ~dst_surface->container->resource.draw_binding); + + return WINED3D_OK; + } +diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c +index 1f34992..61c074f 100644 +--- a/dlls/wined3d/context.c ++++ b/dlls/wined3d/context.c +@@ -3085,7 +3085,7 @@ static void context_setup_target(struct wined3d_context *context, struct wined3d + if (texture->texture_srgb.name) + wined3d_texture_load(texture, context, TRUE); + wined3d_texture_load(texture, context, FALSE); +- surface_invalidate_location(context->current_rt, WINED3D_LOCATION_DRAWABLE); ++ wined3d_resource_invalidate_location(&context->current_rt->resource, WINED3D_LOCATION_DRAWABLE); + } + } + +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index 600afed..70a30f0 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -393,7 +393,7 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c + if (rt) + { + wined3d_resource_validate_location(&rt->resource, rt->container->resource.draw_binding); +- surface_invalidate_location(rt, ~rt->container->resource.draw_binding); ++ wined3d_resource_invalidate_location(&rt->resource, ~rt->container->resource.draw_binding); + } + } + +diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c +index 7034b25..eef7e2c 100644 +--- a/dlls/wined3d/drawprim.c ++++ b/dlls/wined3d/drawprim.c +@@ -626,7 +626,7 @@ void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_co + if (target) + { + surface_load_location(target, context, target->container->resource.draw_binding); +- surface_invalidate_location(target, ~target->container->resource.draw_binding); ++ wined3d_resource_invalidate_location(&target->resource, ~target->container->resource.draw_binding); + } + } + } +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 6c2698a..ef52ed0 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -599,7 +599,7 @@ static void surface_evict_sysmem(struct wined3d_surface *surface) + return; + + wined3d_resource_free_sysmem(&surface->resource); +- surface_invalidate_location(surface, WINED3D_LOCATION_SYSMEM); ++ wined3d_resource_invalidate_location(&surface->resource, WINED3D_LOCATION_SYSMEM); + } + + static void surface_release_client_storage(struct wined3d_surface *surface) +@@ -1185,7 +1185,7 @@ static void surface_remove_pbo(struct wined3d_surface *surface, const struct win + checkGLcall("glDeleteBuffersARB(1, &surface->pbo)"); + + surface->pbo = 0; +- surface_invalidate_location(surface, WINED3D_LOCATION_BUFFER); ++ wined3d_resource_invalidate_location(&surface->resource, WINED3D_LOCATION_BUFFER); + } + + static ULONG surface_resource_incref(struct wined3d_resource *resource) +@@ -1225,7 +1225,7 @@ static void surface_unload(struct wined3d_resource *resource) + surface_prepare_system_memory(surface); + memset(surface->resource.heap_memory, 0, surface->resource.size); + wined3d_resource_validate_location(&surface->resource, WINED3D_LOCATION_SYSMEM); +- surface_invalidate_location(surface, ~WINED3D_LOCATION_SYSMEM); ++ wined3d_resource_invalidate_location(&surface->resource, ~WINED3D_LOCATION_SYSMEM); + + /* We also get here when the ddraw swapchain is destroyed, for example + * for a mode switch. In this case this surface won't necessarily be +@@ -1237,7 +1237,7 @@ static void surface_unload(struct wined3d_resource *resource) + { + surface_prepare_map_memory(surface); + surface_load_location(surface, context, surface->resource.map_binding); +- surface_invalidate_location(surface, ~surface->resource.map_binding); ++ wined3d_resource_invalidate_location(&surface->resource, ~surface->resource.map_binding); + } + + /* Destroy PBOs, but load them into real sysmem before */ +@@ -1275,7 +1275,10 @@ static void surface_unload(struct wined3d_resource *resource) + + static void wined3d_surface_location_invalidated(struct wined3d_resource *resource, DWORD location) + { +- ERR("Not yet implemented.\n"); ++ struct wined3d_surface *surface = surface_from_resource(resource); ++ ++ if (location & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) ++ wined3d_texture_set_dirty(surface->container); + } + + static const struct wined3d_resource_ops surface_resource_ops = +@@ -1742,7 +1745,7 @@ HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface, const P + context_release(context); + + wined3d_resource_validate_location(&dst_surface->resource, WINED3D_LOCATION_TEXTURE_RGB); +- surface_invalidate_location(dst_surface, ~WINED3D_LOCATION_TEXTURE_RGB); ++ wined3d_resource_invalidate_location(&dst_surface->resource, ~WINED3D_LOCATION_TEXTURE_RGB); + + return WINED3D_OK; + } +@@ -1873,7 +1876,7 @@ void surface_load(struct wined3d_surface *surface, struct wined3d_context *conte + + surface_prepare_map_memory(surface); + surface_load_location(surface, context, surface->resource.map_binding); +- surface_invalidate_location(surface, ~surface->resource.map_binding); ++ wined3d_resource_invalidate_location(&surface->resource, ~surface->resource.map_binding); + /* Switching color keying on / off may change the internal format. */ + if (ck_changed) + wined3d_texture_force_reload(surface->container); +@@ -2668,7 +2671,7 @@ HRESULT CDECL wined3d_surface_map(struct wined3d_surface *surface, + } + + if (!(flags & (WINED3D_MAP_NO_DIRTY_UPDATE | WINED3D_MAP_READONLY))) +- surface_invalidate_location(surface, ~surface->resource.map_binding); ++ wined3d_resource_invalidate_location(&surface->resource, ~surface->resource.map_binding); + + switch (surface->resource.map_binding) + { +@@ -2784,7 +2787,7 @@ HRESULT CDECL wined3d_surface_getdc(struct wined3d_surface *surface, HDC *dc) + } + + surface_load_location(surface, context, WINED3D_LOCATION_DIB); +- surface_invalidate_location(surface, ~WINED3D_LOCATION_DIB); ++ wined3d_resource_invalidate_location(&surface->resource, ~WINED3D_LOCATION_DIB); + + if (context) + context_release(context); +@@ -2833,7 +2836,7 @@ HRESULT CDECL wined3d_surface_releasedc(struct wined3d_surface *surface, HDC dc) + context = context_acquire(device, NULL); + + surface_load_location(surface, context, surface->resource.map_binding); +- surface_invalidate_location(surface, WINED3D_LOCATION_DIB); ++ wined3d_resource_invalidate_location(&surface->resource, WINED3D_LOCATION_DIB); + if (context) + context_release(context); + } +@@ -3207,7 +3210,7 @@ static void fb_copy_to_texture_direct(struct wined3d_surface *dst_surface, struc + /* The texture is now most up to date - If the surface is a render target + * and has a drawable, this path is never entered. */ + wined3d_resource_validate_location(&dst_surface->resource, WINED3D_LOCATION_TEXTURE_RGB); +- surface_invalidate_location(dst_surface, ~WINED3D_LOCATION_TEXTURE_RGB); ++ wined3d_resource_invalidate_location(&dst_surface->resource, ~WINED3D_LOCATION_TEXTURE_RGB); + } + + /* Uses the hardware to stretch and flip the image */ +@@ -3275,7 +3278,7 @@ static void fb_copy_to_texture_hwstretch(struct wined3d_surface *dst_surface, st + checkGLcall("glEnable(texture_target)"); + + /* For now invalidate the texture copy of the back buffer. Drawable and sysmem copy are untouched */ +- src_surface->resource.locations &= ~WINED3D_LOCATION_TEXTURE_RGB; ++ wined3d_resource_invalidate_location(&src_surface->resource, WINED3D_LOCATION_TEXTURE_RGB); + } + + /* Make sure that the top pixel is always above the bottom pixel, and keep a separate upside down flag +@@ -3481,7 +3484,7 @@ static void fb_copy_to_texture_hwstretch(struct wined3d_surface *dst_surface, st + /* The texture is now most up to date - If the surface is a render target + * and has a drawable, this path is never entered. */ + wined3d_resource_validate_location(&dst_surface->resource, WINED3D_LOCATION_TEXTURE_RGB); +- surface_invalidate_location(dst_surface, ~WINED3D_LOCATION_TEXTURE_RGB); ++ wined3d_resource_invalidate_location(&dst_surface->resource, ~WINED3D_LOCATION_TEXTURE_RGB); + } + + /* Front buffer coordinates are always full screen coordinates, but our GL +@@ -3794,7 +3797,7 @@ static HRESULT surface_blt_special(struct wined3d_surface *dst_surface, const RE + (old_color_key_flags & WINEDDSD_CKSRCBLT) ? &old_blt_key : NULL); + + wined3d_resource_validate_location(&dst_surface->resource, dst_surface->container->resource.draw_binding); +- surface_invalidate_location(dst_surface, ~dst_surface->container->resource.draw_binding); ++ wined3d_resource_invalidate_location(&dst_surface->resource, ~dst_surface->container->resource.draw_binding); + + return WINED3D_OK; + } +@@ -4038,18 +4041,6 @@ void surface_load_ds_location(struct wined3d_surface *surface, struct wined3d_co + surface->ds_current_size.cy = surface->resource.height; + } + +-void surface_invalidate_location(struct wined3d_surface *surface, DWORD location) +-{ +- TRACE("surface %p, location %s.\n", surface, wined3d_debug_location(location)); +- +- if (location & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) +- wined3d_texture_set_dirty(surface->container); +- surface->resource.locations &= ~location; +- +- if (!surface->resource.locations) +- ERR("Surface %p does not have any up to date location.\n", surface); +-} +- + static DWORD resource_access_from_location(DWORD location) + { + switch (location) +@@ -5528,7 +5519,7 @@ HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const REC + context_release(context); + + wined3d_resource_validate_location(&dst_surface->resource, dst_surface->container->resource.draw_binding); +- surface_invalidate_location(dst_surface, ~dst_surface->container->resource.draw_binding); ++ wined3d_resource_invalidate_location(&dst_surface->resource, ~dst_surface->container->resource.draw_binding); + + return WINED3D_OK; + } +@@ -5657,7 +5648,7 @@ static HRESULT surface_init(struct wined3d_surface *surface, struct wined3d_text + { + wined3d_resource_free_sysmem(&surface->resource); + wined3d_resource_validate_location(&surface->resource, WINED3D_LOCATION_DIB); +- surface_invalidate_location(surface, WINED3D_LOCATION_SYSMEM); ++ wined3d_resource_invalidate_location(&surface->resource, WINED3D_LOCATION_SYSMEM); + } + + return hr; +diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c +index bdb4b67..e64715e 100644 +--- a/dlls/wined3d/swapchain.c ++++ b/dlls/wined3d/swapchain.c +@@ -512,7 +512,7 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT + if (!swapchain->render_to_fbo && render_to_fbo && wined3d_settings.offscreen_rendering_mode == ORM_FBO) + { + surface_load_location(back_buffer, context, WINED3D_LOCATION_TEXTURE_RGB); +- surface_invalidate_location(back_buffer, WINED3D_LOCATION_DRAWABLE); ++ wined3d_resource_invalidate_location(&back_buffer->resource, WINED3D_LOCATION_DRAWABLE); + swapchain->render_to_fbo = TRUE; + swapchain_update_draw_bindings(swapchain); + } +@@ -574,15 +574,15 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT + else + { + wined3d_resource_validate_location(&front->resource, WINED3D_LOCATION_DRAWABLE); +- surface_invalidate_location(front, ~WINED3D_LOCATION_DRAWABLE); ++ wined3d_resource_invalidate_location(&front->resource, ~WINED3D_LOCATION_DRAWABLE); + wined3d_resource_validate_location(&back_buffer->resource, WINED3D_LOCATION_DRAWABLE); +- surface_invalidate_location(back_buffer, ~WINED3D_LOCATION_DRAWABLE); ++ wined3d_resource_invalidate_location(&back_buffer->resource, ~WINED3D_LOCATION_DRAWABLE); + } + } + else + { + wined3d_resource_validate_location(&front->resource, WINED3D_LOCATION_DRAWABLE); +- surface_invalidate_location(front, ~WINED3D_LOCATION_DRAWABLE); ++ wined3d_resource_invalidate_location(&front->resource, ~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. If it is FLIP however, +@@ -591,7 +591,7 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT + if (swapchain->desc.swap_effect == WINED3D_SWAP_EFFECT_FLIP) + { + wined3d_resource_validate_location(&back_buffer->resource, back_buffer->container->resource.draw_binding); +- surface_invalidate_location(back_buffer, ~back_buffer->container->resource.draw_binding); ++ wined3d_resource_invalidate_location(&back_buffer->resource, ~back_buffer->container->resource.draw_binding); + } + } + +@@ -866,7 +866,7 @@ static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3 + if (!(device->wined3d->flags & WINED3D_NO3D)) + { + wined3d_resource_validate_location(&front_buffer->resource, WINED3D_LOCATION_DRAWABLE); +- surface_invalidate_location(front_buffer, ~WINED3D_LOCATION_DRAWABLE); ++ wined3d_resource_invalidate_location(&front_buffer->resource, ~WINED3D_LOCATION_DRAWABLE); + } + + /* MSDN says we're only allowed a single fullscreen swapchain per device, +diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c +index c42e475..941d935 100644 +--- a/dlls/wined3d/texture.c ++++ b/dlls/wined3d/texture.c +@@ -832,7 +832,7 @@ static void texture2d_sub_resource_add_dirty_region(struct wined3d_resource *sub + 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); ++ wined3d_resource_invalidate_location(&surface->resource, ~surface->resource.map_binding); + } + + static void texture2d_sub_resource_cleanup(struct wined3d_resource *sub_resource) +@@ -844,9 +844,7 @@ static void texture2d_sub_resource_cleanup(struct wined3d_resource *sub_resource + + static void texture2d_sub_resource_invalidate_location(struct wined3d_resource *sub_resource, DWORD location) + { +- struct wined3d_surface *surface = surface_from_resource(sub_resource); +- +- surface_invalidate_location(surface, location); ++ wined3d_resource_invalidate_location(sub_resource, location); + } + + /* Context activation is done by the caller. */ +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 60d1b56..640aa95 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2351,7 +2351,6 @@ HRESULT surface_color_fill(struct wined3d_surface *s, + 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; +-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; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0016-wined3d-Move-bitmap_data-and-user_memory-into-the-re.patch b/patches/wined3d-CSMT_Main/0016-wined3d-Move-bitmap_data-and-user_memory-into-the-re.patch new file mode 100644 index 00000000..25c99b3c --- /dev/null +++ b/patches/wined3d-CSMT_Main/0016-wined3d-Move-bitmap_data-and-user_memory-into-the-re.patch @@ -0,0 +1,171 @@ +From 2341723442d5ab7fb42bb82d066b306cc458813d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 16 Jan 2014 22:04:55 +0100 +Subject: wined3d: Move bitmap_data and user_memory into the resource. + +I may want to change this to keep this in the surface. Not sure yet. +--- + dlls/wined3d/surface.c | 32 ++++++++++++++++---------------- + dlls/wined3d/swapchain.c | 6 +++--- + dlls/wined3d/wined3d_private.h | 4 +--- + 3 files changed, 20 insertions(+), 22 deletions(-) + +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index ef52ed0..c689880 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -88,7 +88,7 @@ static void surface_cleanup(struct wined3d_surface *surface) + { + DeleteDC(surface->hDC); + DeleteObject(surface->dib.DIBsection); +- surface->dib.bitmap_data = NULL; ++ surface->resource.bitmap_data = NULL; + } + + if (surface->overlay_dest) +@@ -456,7 +456,7 @@ static HRESULT surface_create_dib_section(struct wined3d_surface *surface) + TRACE("Creating a DIB section with size %dx%dx%d, size=%d.\n", + b_info->bmiHeader.biWidth, b_info->bmiHeader.biHeight, + b_info->bmiHeader.biBitCount, b_info->bmiHeader.biSizeImage); +- surface->dib.DIBsection = CreateDIBSection(0, b_info, DIB_RGB_COLORS, &surface->dib.bitmap_data, 0, 0); ++ surface->dib.DIBsection = CreateDIBSection(0, b_info, DIB_RGB_COLORS, &surface->resource.bitmap_data, 0, 0); + + if (!surface->dib.DIBsection) + { +@@ -465,7 +465,7 @@ static HRESULT surface_create_dib_section(struct wined3d_surface *surface) + return HRESULT_FROM_WIN32(GetLastError()); + } + +- TRACE("DIBSection at %p.\n", surface->dib.bitmap_data); ++ TRACE("DIBSection at %p.\n", surface->resource.bitmap_data); + surface->dib.bitmap_size = b_info->bmiHeader.biSizeImage; + + HeapFree(GetProcessHeap(), 0, b_info); +@@ -490,13 +490,13 @@ static void surface_get_memory(const struct wined3d_surface *surface, struct win + } + if (location & WINED3D_LOCATION_USER_MEMORY) + { +- data->addr = surface->user_memory; ++ data->addr = surface->resource.user_memory; + data->buffer_object = 0; + return; + } + if (location & WINED3D_LOCATION_DIB) + { +- data->addr = surface->dib.bitmap_data; ++ data->addr = surface->resource.bitmap_data; + data->buffer_object = 0; + return; + } +@@ -569,13 +569,13 @@ void surface_prepare_map_memory(struct wined3d_surface *surface) + break; + + case WINED3D_LOCATION_USER_MEMORY: +- if (!surface->user_memory) +- ERR("Map binding is set to WINED3D_LOCATION_USER_MEMORY but surface->user_memory is NULL.\n"); ++ if (!surface->resource.user_memory) ++ ERR("Map binding is set to WINED3D_LOCATION_USER_MEMORY but surface->resource.user_memory is NULL.\n"); + break; + + case WINED3D_LOCATION_DIB: +- if (!surface->dib.bitmap_data) +- ERR("Map binding is set to WINED3D_LOCATION_DIB but surface->dib.bitmap_data is NULL.\n"); ++ if (!surface->resource.bitmap_data) ++ ERR("Map binding is set to WINED3D_LOCATION_DIB but surface->resource.bitmap_data is NULL.\n"); + break; + + case WINED3D_LOCATION_BUFFER: +@@ -2190,7 +2190,7 @@ HRESULT wined3d_surface_update_desc(struct wined3d_surface *surface, + { + DeleteDC(surface->hDC); + DeleteObject(surface->dib.DIBsection); +- surface->dib.bitmap_data = NULL; ++ surface->resource.bitmap_data = NULL; + surface->flags &= ~SFLAG_DIBSECTION; + create_dib = TRUE; + } +@@ -2222,7 +2222,7 @@ HRESULT wined3d_surface_update_desc(struct wined3d_surface *surface, + else + surface->flags &= ~SFLAG_NONPOW2; + +- if ((surface->user_memory = mem)) ++ if ((surface->resource.user_memory = mem)) + { + surface->resource.map_binding = WINED3D_LOCATION_USER_MEMORY; + valid_location = WINED3D_LOCATION_USER_MEMORY; +@@ -2680,11 +2680,11 @@ HRESULT CDECL wined3d_surface_map(struct wined3d_surface *surface, + break; + + case WINED3D_LOCATION_USER_MEMORY: +- base_memory = surface->user_memory; ++ base_memory = surface->resource.user_memory; + break; + + case WINED3D_LOCATION_DIB: +- base_memory = surface->dib.bitmap_data; ++ base_memory = surface->resource.bitmap_data; + break; + + case WINED3D_LOCATION_BUFFER: +@@ -3052,9 +3052,9 @@ void flip_surface(struct wined3d_surface *front, struct wined3d_surface *back) + { + void* tmp; + +- tmp = front->dib.bitmap_data; +- front->dib.bitmap_data = back->dib.bitmap_data; +- back->dib.bitmap_data = tmp; ++ tmp = front->resource.bitmap_data; ++ front->resource.bitmap_data = back->resource.bitmap_data; ++ back->resource.bitmap_data = tmp; + + tmp = front->resource.heap_memory; + front->resource.heap_memory = back->resource.heap_memory; +diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c +index e64715e..17f1afe 100644 +--- a/dlls/wined3d/swapchain.c ++++ b/dlls/wined3d/swapchain.c +@@ -695,9 +695,9 @@ static void swapchain_gdi_present(struct wined3d_swapchain *swapchain, const REC + { + void *tmp; + +- tmp = front->dib.bitmap_data; +- front->dib.bitmap_data = back->dib.bitmap_data; +- back->dib.bitmap_data = tmp; ++ tmp = front->resource.bitmap_data; ++ front->resource.bitmap_data = back->resource.bitmap_data; ++ back->resource.bitmap_data = tmp; + + if (front->resource.heap_memory) + ERR("GDI Surface %p has heap memory allocated.\n", front); +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 640aa95..52280a7 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2080,7 +2080,7 @@ struct wined3d_resource + UINT depth; + UINT size; + DWORD priority; +- void *heap_memory; ++ void *heap_memory, *user_memory, *bitmap_data; + UINT custom_row_pitch, custom_slice_pitch; + struct list resource_list_entry; + DWORD locations; +@@ -2263,7 +2263,6 @@ void wined3d_volume_upload_data(struct wined3d_volume *volume, const struct wine + struct wined3d_surface_dib + { + HBITMAP DIBsection; +- void *bitmap_data; + UINT bitmap_size; + }; + +@@ -2297,7 +2296,6 @@ struct wined3d_surface + struct wined3d_resource resource; + const struct wined3d_surface_ops *surface_ops; + struct wined3d_texture *container; +- void *user_memory; + + DWORD flags; + +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0017-wined3d-Move-load_location-into-the-resource.patch b/patches/wined3d-CSMT_Main/0017-wined3d-Move-load_location-into-the-resource.patch new file mode 100644 index 00000000..57bd4218 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0017-wined3d-Move-load_location-into-the-resource.patch @@ -0,0 +1,309 @@ +From 647e3b2622558e3a8350bb3521fdbd3119b92d95 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 3 Oct 2013 12:47:01 +0200 +Subject: wined3d: Move load_location into the resource. + +The resource part of load_location will handle transfers between sysmem +locations (heap memory, user memory, dib) and buffers. Texture loading +and downloading from textures will be delegated to surfaces / volumes. +--- + dlls/wined3d/buffer.c | 8 +++++++ + dlls/wined3d/resource.c | 50 ++++++++++++++++++++++++++++++++++++++++++ + dlls/wined3d/surface.c | 12 ++++++++-- + dlls/wined3d/texture.c | 8 +++++++ + dlls/wined3d/volume.c | 42 ++++++++--------------------------- + dlls/wined3d/wined3d_private.h | 7 +++++- + 6 files changed, 91 insertions(+), 36 deletions(-) + +diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c +index d9bc820..2e44f0f 100644 +--- a/dlls/wined3d/buffer.c ++++ b/dlls/wined3d/buffer.c +@@ -1128,12 +1128,20 @@ static void wined3d_buffer_location_invalidated(struct wined3d_resource *resourc + ERR("Not yet implemented.\n"); + } + ++/* Context activation is done by the caller. */ ++static void wined3d_buffer_load_location(struct wined3d_resource *resource, ++ struct wined3d_context *context, DWORD location) ++{ ++ ERR("Not yet implemented.\n"); ++} ++ + static const struct wined3d_resource_ops buffer_resource_ops = + { + buffer_resource_incref, + buffer_resource_decref, + buffer_unload, + wined3d_buffer_location_invalidated, ++ wined3d_buffer_load_location, + }; + + static HRESULT buffer_init(struct wined3d_buffer *buffer, struct wined3d_device *device, +diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c +index 9d2db2b..63f8584 100644 +--- a/dlls/wined3d/resource.c ++++ b/dlls/wined3d/resource.c +@@ -348,6 +348,56 @@ void wined3d_resource_invalidate_location(struct wined3d_resource *resource, DWO + resource->resource_ops->resource_location_invalidated(resource, location); + } + ++DWORD wined3d_resource_access_from_location(DWORD location) ++{ ++ switch (location) ++ { ++ case WINED3D_LOCATION_DISCARDED: ++ return 0; ++ ++ case WINED3D_LOCATION_SYSMEM: ++ case WINED3D_LOCATION_USER_MEMORY: ++ case WINED3D_LOCATION_DIB: ++ return WINED3D_RESOURCE_ACCESS_CPU; ++ ++ case WINED3D_LOCATION_BUFFER: ++ case WINED3D_LOCATION_TEXTURE_RGB: ++ case WINED3D_LOCATION_TEXTURE_SRGB: ++ case WINED3D_LOCATION_DRAWABLE: ++ case WINED3D_LOCATION_RB_MULTISAMPLE: ++ case WINED3D_LOCATION_RB_RESOLVED: ++ return WINED3D_RESOURCE_ACCESS_GPU; ++ ++ default: ++ FIXME("Unhandled location %#x.\n", location); ++ return 0; ++ } ++} ++ ++/* Context activation is optionally by the caller. Context may be NULL. */ ++void wined3d_resource_load_location(struct wined3d_resource *resource, ++ struct wined3d_context *context, DWORD location) ++{ ++ DWORD required_access = wined3d_resource_access_from_location(location); ++ ++ if ((resource->locations & location) == location) ++ { ++ TRACE("Location(s) already up to date.\n"); ++ return; ++ } ++ ++ /* Keep this a WARN for now until surfaces are cleaned up. */ ++ if ((resource->access_flags & required_access) != required_access) ++ WARN("Operation requires %#x access, but resource only has %#x.\n", ++ required_access, resource->access_flags); ++ ++ /* Context is NULL in ddraw-only operation without OpenGL. */ ++ if (!context) ++ ERR("A context is required for non-sysmem operation.\n"); ++ ++ resource->resource_ops->resource_load_location(resource, context, location); ++} ++ + void CDECL wined3d_resource_get_pitch(const struct wined3d_resource *resource, UINT *row_pitch, + UINT *slice_pitch) + { +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index c689880..de57d25 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -1281,12 +1281,20 @@ static void wined3d_surface_location_invalidated(struct wined3d_resource *resour + wined3d_texture_set_dirty(surface->container); + } + ++/* Context activation is done by the caller. */ ++static void wined3d_surface_load_location(struct wined3d_resource *resource, ++ struct wined3d_context *context, DWORD location) ++{ ++ ERR("Not yet implemented.\n"); ++} ++ + static const struct wined3d_resource_ops surface_resource_ops = + { + surface_resource_incref, + surface_resource_decref, + surface_unload, + wined3d_surface_location_invalidated, ++ wined3d_surface_load_location, + }; + + static const struct wined3d_surface_ops surface_ops = +@@ -4041,7 +4049,7 @@ void surface_load_ds_location(struct wined3d_surface *surface, struct wined3d_co + surface->ds_current_size.cy = surface->resource.height; + } + +-static DWORD resource_access_from_location(DWORD location) ++static DWORD surface_access_from_location(DWORD location) + { + switch (location) + { +@@ -4380,7 +4388,7 @@ void surface_load_location(struct wined3d_surface *surface, struct wined3d_conte + + if (WARN_ON(d3d_surface)) + { +- DWORD required_access = resource_access_from_location(location); ++ DWORD required_access = surface_access_from_location(location); + if ((surface->resource.access_flags & required_access) != required_access) + WARN("Operation requires %#x access, but surface only has %#x.\n", + required_access, surface->resource.access_flags); +diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c +index 941d935..ea9eacc 100644 +--- a/dlls/wined3d/texture.c ++++ b/dlls/wined3d/texture.c +@@ -989,12 +989,20 @@ static void wined3d_texture_load_location_invalidated(struct wined3d_resource *r + ERR("Should not be called on textures.\n"); + } + ++/* Context activation is done by the caller. */ ++static void wined3d_texture_load_location(struct wined3d_resource *resource, ++ struct wined3d_context *context, DWORD location) ++{ ++ ERR("Should not be called on textures.\n"); ++} ++ + static const struct wined3d_resource_ops texture_resource_ops = + { + texture_resource_incref, + texture_resource_decref, + wined3d_texture_unload, + wined3d_texture_load_location_invalidated, ++ wined3d_texture_load_location, + }; + + static HRESULT cubetexture_init(struct wined3d_texture *texture, const struct wined3d_resource_desc *desc, +diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c +index 6921b87..c93a1ef 100644 +--- a/dlls/wined3d/volume.c ++++ b/dlls/wined3d/volume.c +@@ -136,27 +136,6 @@ static void wined3d_volume_evict_sysmem(struct wined3d_volume *volume) + wined3d_resource_invalidate_location(&volume->resource, 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; +- } +-} +- + /* Context activation is done by the caller. */ + static void wined3d_volume_srgb_transfer(struct wined3d_volume *volume, + struct wined3d_context *context, BOOL dest_is_srgb) +@@ -196,21 +175,17 @@ static BOOL wined3d_volume_can_evict(const struct wined3d_volume *volume) + + return TRUE; + } ++ + /* Context activation is done by the caller. */ +-static void wined3d_volume_load_location(struct wined3d_volume *volume, ++static void wined3d_volume_load_location(struct wined3d_resource *resource, + struct wined3d_context *context, DWORD location) + { +- DWORD required_access = volume_access_from_location(location); ++ struct wined3d_volume *volume = volume_from_resource(resource); ++ DWORD required_access = wined3d_resource_access_from_location(location); + + TRACE("Volume %p, loading %s, have %s.\n", volume, wined3d_debug_location(location), + wined3d_debug_location(volume->resource.locations)); + +- if ((volume->resource.locations & location) == location) +- { +- TRACE("Location(s) already up to date.\n"); +- return; +- } +- + if ((volume->resource.access_flags & required_access) != required_access) + { + ERR("Operation requires %#x access, but volume only has %#x.\n", +@@ -332,7 +307,7 @@ static void wined3d_volume_load_location(struct wined3d_volume *volume, + void wined3d_volume_load(struct wined3d_volume *volume, struct wined3d_context *context, BOOL srgb_mode) + { + wined3d_texture_prepare_texture(volume->container, context, srgb_mode); +- wined3d_volume_load_location(volume, context, ++ wined3d_resource_load_location(&volume->resource, context, + srgb_mode ? WINED3D_LOCATION_TEXTURE_SRGB : WINED3D_LOCATION_TEXTURE_RGB); + } + +@@ -391,7 +366,7 @@ static void volume_unload(struct wined3d_resource *resource) + if (volume_prepare_system_memory(volume)) + { + context = context_acquire(device, NULL); +- wined3d_volume_load_location(volume, context, WINED3D_LOCATION_SYSMEM); ++ wined3d_resource_load_location(&volume->resource, context, WINED3D_LOCATION_SYSMEM); + context_release(context); + wined3d_resource_invalidate_location(&volume->resource, ~WINED3D_LOCATION_SYSMEM); + } +@@ -546,7 +521,7 @@ HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume, + if (flags & WINED3D_MAP_DISCARD) + wined3d_resource_validate_location(&volume->resource, WINED3D_LOCATION_BUFFER); + else +- wined3d_volume_load_location(volume, context, WINED3D_LOCATION_BUFFER); ++ wined3d_resource_load_location(&volume->resource, context, WINED3D_LOCATION_BUFFER); + + GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, volume->pbo)); + +@@ -584,7 +559,7 @@ HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume, + else if (!(volume->resource.locations & WINED3D_LOCATION_SYSMEM)) + { + context = context_acquire(device, NULL); +- wined3d_volume_load_location(volume, context, WINED3D_LOCATION_SYSMEM); ++ wined3d_resource_load_location(&volume->resource, context, WINED3D_LOCATION_SYSMEM); + context_release(context); + } + base_memory = volume->resource.heap_memory; +@@ -699,6 +674,7 @@ static const struct wined3d_resource_ops volume_resource_ops = + volume_resource_decref, + volume_unload, + wined3d_volume_location_invalidated, ++ wined3d_volume_load_location, + }; + + static HRESULT volume_init(struct wined3d_volume *volume, struct wined3d_texture *container, +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 52280a7..b1e4cb6 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2058,6 +2058,8 @@ struct wined3d_resource_ops + ULONG (*resource_decref)(struct wined3d_resource *resource); + void (*resource_unload)(struct wined3d_resource *resource); + void (*resource_location_invalidated)(struct wined3d_resource *resource, DWORD location); ++ void (*resource_load_location)(struct wined3d_resource *resource, ++ struct wined3d_context *context, DWORD location); + }; + + struct wined3d_resource +@@ -2108,15 +2110,18 @@ HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device * + 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; ++DWORD wined3d_resource_access_from_location(DWORD location) DECLSPEC_HIDDEN; + 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; ++void wined3d_resource_invalidate_location(struct wined3d_resource *resource, DWORD location) DECLSPEC_HIDDEN; + BOOL wined3d_resource_is_offscreen(struct wined3d_resource *resource) DECLSPEC_HIDDEN; ++void wined3d_resource_load_location(struct wined3d_resource *resource, ++ struct wined3d_context *context, DWORD location) 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; + void wined3d_resource_validate_location(struct wined3d_resource *resource, DWORD location) DECLSPEC_HIDDEN; +-void wined3d_resource_invalidate_location(struct wined3d_resource *resource, DWORD location) DECLSPEC_HIDDEN; + + /* Tests show that the start address of resources is 32 byte aligned */ + #define RESOURCE_ALIGNMENT 16 +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0018-wined3d-Replace-surface_load_location-with-resource_.patch b/patches/wined3d-CSMT_Main/0018-wined3d-Replace-surface_load_location-with-resource_.patch new file mode 100644 index 00000000..f4e7f0ca --- /dev/null +++ b/patches/wined3d-CSMT_Main/0018-wined3d-Replace-surface_load_location-with-resource_.patch @@ -0,0 +1,411 @@ +From a1e69a04b1cb46aa0d16b4bc4b696321e0698972 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Sun, 17 Nov 2013 20:33:17 +0100 +Subject: wined3d: Replace surface_load_location with resource_load_location. + +FIXME: Check if this patch is complete enough to make sense. +--- + dlls/wined3d/context.c | 2 +- + dlls/wined3d/device.c | 2 +- + dlls/wined3d/drawprim.c | 2 +- + dlls/wined3d/surface.c | 113 +++++++++++++---------------------------- + dlls/wined3d/swapchain.c | 8 +-- + dlls/wined3d/texture.c | 2 +- + dlls/wined3d/wined3d_private.h | 2 - + 7 files changed, 44 insertions(+), 87 deletions(-) + +diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c +index 61c074f..cc60348 100644 +--- a/dlls/wined3d/context.c ++++ b/dlls/wined3d/context.c +@@ -2215,7 +2215,7 @@ static void context_validate_onscreen_formats(struct wined3d_context *context, + WARN("Depth stencil format is not supported by WGL, rendering the backbuffer in an FBO\n"); + + /* The currently active context is the necessary context to access the swapchain's onscreen buffers */ +- surface_load_location(context->current_rt, context, WINED3D_LOCATION_TEXTURE_RGB); ++ wined3d_resource_load_location(&context->current_rt->resource, context, WINED3D_LOCATION_TEXTURE_RGB); + swapchain->render_to_fbo = TRUE; + swapchain_update_draw_bindings(swapchain); + context_set_render_offscreen(context, TRUE); +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index 70a30f0..565a92c 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -323,7 +323,7 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c + { + struct wined3d_surface *rt = wined3d_rendertarget_view_get_surface(fb->render_targets[i]); + if (rt) +- surface_load_location(rt, context, rt->container->resource.draw_binding); ++ wined3d_resource_load_location(&rt->resource, context, rt->container->resource.draw_binding); + } + } + +diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c +index eef7e2c..62b7032 100644 +--- a/dlls/wined3d/drawprim.c ++++ b/dlls/wined3d/drawprim.c +@@ -625,7 +625,7 @@ void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_co + struct wined3d_surface *target = wined3d_rendertarget_view_get_surface(device->fb.render_targets[i]); + if (target) + { +- surface_load_location(target, context, target->container->resource.draw_binding); ++ wined3d_resource_load_location(&target->resource, context, target->container->resource.draw_binding); + wined3d_resource_invalidate_location(&target->resource, ~target->container->resource.draw_binding); + } + } +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index de57d25..6154315 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -759,7 +759,7 @@ static void surface_unmap(struct wined3d_surface *surface) + + if (device->d3d_initialized) + context = context_acquire(device, surface); +- surface_load_location(surface, context, surface->container->resource.draw_binding); ++ wined3d_resource_load_location(&surface->resource, context, surface->container->resource.draw_binding); + if (context) + context_release(context); + } +@@ -825,9 +825,9 @@ static void surface_depth_blt_fbo(const struct wined3d_device *device, + + /* Make sure the locations are up-to-date. Loading the destination + * surface isn't required if the entire surface is overwritten. */ +- surface_load_location(src_surface, context, src_location); ++ wined3d_resource_load_location(&src_surface->resource, context, src_location); + if (!surface_is_full_rect(dst_surface, dst_rect)) +- surface_load_location(dst_surface, context, dst_location); ++ wined3d_resource_load_location(&dst_surface->resource, context, dst_location); + + gl_info = context->gl_info; + +@@ -916,9 +916,9 @@ static void surface_blt_fbo(const struct wined3d_device *device, + * surface isn't required if the entire surface is overwritten. (And is + * in fact harmful if we're being called by surface_load_location() with + * the purpose of loading the destination surface.) */ +- surface_load_location(src_surface, old_ctx, src_location); ++ wined3d_resource_load_location(&src_surface->resource, old_ctx, src_location); + if (!surface_is_full_rect(dst_surface, &dst_rect)) +- surface_load_location(dst_surface, old_ctx, dst_location); ++ wined3d_resource_load_location(&dst_surface->resource, old_ctx, dst_location); + + if (src_location == WINED3D_LOCATION_DRAWABLE) required_rt = src_surface; + else if (dst_location == WINED3D_LOCATION_DRAWABLE) required_rt = dst_surface; +@@ -1236,7 +1236,7 @@ static void surface_unload(struct wined3d_resource *resource) + else + { + surface_prepare_map_memory(surface); +- surface_load_location(surface, context, surface->resource.map_binding); ++ wined3d_resource_load_location(&surface->resource, context, surface->resource.map_binding); + wined3d_resource_invalidate_location(&surface->resource, ~surface->resource.map_binding); + } + +@@ -1281,22 +1281,6 @@ static void wined3d_surface_location_invalidated(struct wined3d_resource *resour + wined3d_texture_set_dirty(surface->container); + } + +-/* Context activation is done by the caller. */ +-static void wined3d_surface_load_location(struct wined3d_resource *resource, +- struct wined3d_context *context, DWORD location) +-{ +- ERR("Not yet implemented.\n"); +-} +- +-static const struct wined3d_resource_ops surface_resource_ops = +-{ +- surface_resource_incref, +- surface_resource_decref, +- surface_unload, +- wined3d_surface_location_invalidated, +- wined3d_surface_load_location, +-}; +- + static const struct wined3d_surface_ops surface_ops = + { + surface_private_setup, +@@ -1740,7 +1724,7 @@ HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface, const P + if (update_w == dst_w && update_h == dst_h) + wined3d_texture_prepare_texture(dst_surface->container, context, FALSE); + else +- surface_load_location(dst_surface, context, WINED3D_LOCATION_TEXTURE_RGB); ++ wined3d_resource_load_location(&dst_surface->resource, context, WINED3D_LOCATION_TEXTURE_RGB); + wined3d_texture_bind(dst_surface->container, context, FALSE); + + surface_get_memory(src_surface, &data, src_surface->resource.locations); +@@ -1883,7 +1867,7 @@ void surface_load(struct wined3d_surface *surface, struct wined3d_context *conte + * the surface. Make sure we have it. */ + + surface_prepare_map_memory(surface); +- surface_load_location(surface, context, surface->resource.map_binding); ++ wined3d_resource_load_location(&surface->resource, context, surface->resource.map_binding); + wined3d_resource_invalidate_location(&surface->resource, ~surface->resource.map_binding); + /* Switching color keying on / off may change the internal format. */ + if (ck_changed) +@@ -1899,7 +1883,7 @@ void surface_load(struct wined3d_surface *surface, struct wined3d_context *conte + return; + } + +- surface_load_location(surface, context, location); ++ wined3d_resource_load_location(&surface->resource, context, location); + surface_evict_sysmem(surface); + } + +@@ -2673,7 +2657,7 @@ HRESULT CDECL wined3d_surface_map(struct wined3d_surface *surface, + + if (surface->resource.device->d3d_initialized) + context = context_acquire(surface->resource.device, NULL); +- surface_load_location(surface, context, surface->resource.map_binding); ++ wined3d_resource_load_location(&surface->resource, context, surface->resource.map_binding); + if (context) + context_release(context); + } +@@ -2778,7 +2762,7 @@ HRESULT CDECL wined3d_surface_getdc(struct wined3d_surface *surface, HDC *dc) + { + if (surface->flags & SFLAG_CLIENT) + { +- surface_load_location(surface, context, WINED3D_LOCATION_SYSMEM); ++ wined3d_resource_load_location(&surface->resource, context, WINED3D_LOCATION_SYSMEM); + surface_release_client_storage(surface); + } + hr = surface_create_dib_section(surface); +@@ -2794,7 +2778,7 @@ HRESULT CDECL wined3d_surface_getdc(struct wined3d_surface *surface, HDC *dc) + surface->resource.map_binding = WINED3D_LOCATION_DIB; + } + +- surface_load_location(surface, context, WINED3D_LOCATION_DIB); ++ wined3d_resource_load_location(&surface->resource, context, WINED3D_LOCATION_DIB); + wined3d_resource_invalidate_location(&surface->resource, ~WINED3D_LOCATION_DIB); + + if (context) +@@ -2843,7 +2827,7 @@ HRESULT CDECL wined3d_surface_releasedc(struct wined3d_surface *surface, HDC dc) + if (device->d3d_initialized) + context = context_acquire(device, NULL); + +- surface_load_location(surface, context, surface->resource.map_binding); ++ wined3d_resource_load_location(&surface->resource, context, surface->resource.map_binding); + wined3d_resource_invalidate_location(&surface->resource, WINED3D_LOCATION_DIB); + if (context) + context_release(context); +@@ -3555,8 +3539,8 @@ static void surface_blt_to_drawable(const struct wined3d_device *device, + gl_info = context->gl_info; + + /* Make sure the surface is up-to-date. This should probably use +- * surface_load_location() and worry about the destination surface too, +- * unless we're overwriting it completely. */ ++ * wined3d_resource_load_location() and worry about the destination ++ * surface too, unless we're overwriting it completely. */ + wined3d_texture_load(src_surface->container, context, FALSE); + + /* Activate the destination context, set it up for blitting */ +@@ -4049,29 +4033,6 @@ void surface_load_ds_location(struct wined3d_surface *surface, struct wined3d_co + surface->ds_current_size.cy = surface->resource.height; + } + +-static DWORD surface_access_from_location(DWORD location) +-{ +- switch (location) +- { +- case WINED3D_LOCATION_SYSMEM: +- case WINED3D_LOCATION_USER_MEMORY: +- case WINED3D_LOCATION_DIB: +- case WINED3D_LOCATION_BUFFER: +- return WINED3D_RESOURCE_ACCESS_CPU; +- +- case WINED3D_LOCATION_DRAWABLE: +- case WINED3D_LOCATION_TEXTURE_SRGB: +- case WINED3D_LOCATION_TEXTURE_RGB: +- case WINED3D_LOCATION_RB_MULTISAMPLE: +- case WINED3D_LOCATION_RB_RESOLVED: +- return WINED3D_RESOURCE_ACCESS_GPU; +- +- default: +- FIXME("Unhandled location %#x.\n", location); +- return 0; +- } +-} +- + static void surface_copy_simple_location(struct wined3d_surface *surface, DWORD location) + { + struct wined3d_device *device = surface->resource.device; +@@ -4121,7 +4082,7 @@ static void surface_load_sysmem(struct wined3d_surface *surface, + } + + if (surface->resource.locations & (WINED3D_LOCATION_RB_MULTISAMPLE | WINED3D_LOCATION_RB_RESOLVED)) +- surface_load_location(surface, context, WINED3D_LOCATION_TEXTURE_RGB); ++ wined3d_resource_load_location(&surface->resource, context, WINED3D_LOCATION_TEXTURE_RGB); + + /* Download the surface to system memory. */ + if (surface->resource.locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) +@@ -4157,7 +4118,7 @@ static HRESULT surface_load_drawable(struct wined3d_surface *surface, + } + + surface_get_rect(surface, NULL, &r); +- surface_load_location(surface, context, WINED3D_LOCATION_TEXTURE_RGB); ++ wined3d_resource_load_location(&surface->resource, context, WINED3D_LOCATION_TEXTURE_RGB); + surface_blt_to_drawable(surface->resource.device, context, + WINED3D_TEXF_POINT, FALSE, surface, &r, surface, &r); + +@@ -4230,7 +4191,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + /* Performance warning... */ + FIXME("Downloading RGB surface %p to reload it as sRGB.\n", surface); + surface_prepare_map_memory(surface); +- surface_load_location(surface, context, surface->resource.map_binding); ++ wined3d_resource_load_location(&surface->resource, context, surface->resource.map_binding); + } + } + else +@@ -4241,7 +4202,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + /* Performance warning... */ + FIXME("Downloading sRGB surface %p to reload it as RGB.\n", surface); + surface_prepare_map_memory(surface); +- surface_load_location(surface, context, surface->resource.map_binding); ++ wined3d_resource_load_location(&surface->resource, context, surface->resource.map_binding); + } + } + +@@ -4250,7 +4211,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + WARN("Trying to load a texture from sysmem, but no simple location is valid.\n"); + /* Lets hope we get it from somewhere... */ + surface_prepare_system_memory(surface); +- surface_load_location(surface, context, WINED3D_LOCATION_SYSMEM); ++ wined3d_resource_load_location(&surface->resource, context, WINED3D_LOCATION_SYSMEM); + } + + wined3d_texture_prepare_texture(texture, context, srgb); +@@ -4283,7 +4244,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + surface->resource.map_binding = WINED3D_LOCATION_SYSMEM; + + surface_prepare_map_memory(surface); +- surface_load_location(surface, context, surface->resource.map_binding); ++ wined3d_resource_load_location(&surface->resource, context, surface->resource.map_binding); + surface_remove_pbo(surface, gl_info); + } + +@@ -4351,9 +4312,11 @@ static void surface_multisample_resolve(struct wined3d_surface *surface, struct + surface, WINED3D_LOCATION_RB_MULTISAMPLE, &rect, surface, WINED3D_LOCATION_RB_RESOLVED, &rect); + } + +-/* Context activation is done by the caller. Context may be NULL in ddraw-only mode. */ +-void surface_load_location(struct wined3d_surface *surface, struct wined3d_context *context, DWORD location) ++/* Context activation is done by the caller. */ ++static void wined3d_surface_load_location(struct wined3d_resource *resource, ++ struct wined3d_context *context, DWORD location) + { ++ struct wined3d_surface *surface = surface_from_resource(resource); + HRESULT hr; + + TRACE("surface %p, location %s.\n", surface, wined3d_debug_location(location)); +@@ -4380,20 +4343,6 @@ void surface_load_location(struct wined3d_surface *surface, struct wined3d_conte + } + } + +- if (surface->resource.locations & location) +- { +- TRACE("Location already up to date.\n"); +- return; +- } +- +- if (WARN_ON(d3d_surface)) +- { +- DWORD required_access = surface_access_from_location(location); +- if ((surface->resource.access_flags & required_access) != required_access) +- WARN("Operation requires %#x access, but surface only has %#x.\n", +- required_access, surface->resource.access_flags); +- } +- + if (!surface->resource.locations) + { + ERR("Surface %p does not have any up to date location.\n", surface); +@@ -5482,7 +5431,8 @@ HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const REC + if (!wined3d_resource_is_offscreen(&dst_surface->container->resource)) + { + struct wined3d_context *context = context_acquire(device, dst_surface); +- surface_load_location(dst_surface, context, dst_surface->container->resource.draw_binding); ++ wined3d_resource_load_location(&dst_surface->resource, context, ++ dst_surface->container->resource.draw_binding); + context_release(context); + } + return WINED3D_OK; +@@ -5557,6 +5507,15 @@ cpu: + return surface_cpu_blt(dst_surface, &dst_rect, src_surface, &src_rect, flags, fx, filter); + } + ++static const struct wined3d_resource_ops surface_resource_ops = ++{ ++ surface_resource_incref, ++ surface_resource_decref, ++ surface_unload, ++ wined3d_surface_location_invalidated, ++ wined3d_surface_load_location, ++}; ++ + static HRESULT surface_init(struct wined3d_surface *surface, struct wined3d_texture *container, + const struct wined3d_resource_desc *desc, GLenum target, unsigned int level, unsigned int layer, DWORD flags) + { +diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c +index 17f1afe..e1a5b8a 100644 +--- a/dlls/wined3d/swapchain.c ++++ b/dlls/wined3d/swapchain.c +@@ -309,7 +309,7 @@ static void swapchain_blit(const struct wined3d_swapchain *swapchain, + if (backbuffer->resource.multisample_type) + { + location = WINED3D_LOCATION_RB_RESOLVED; +- surface_load_location(backbuffer, context, location); ++ wined3d_resource_load_location(&backbuffer->resource, context, location); + } + + context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, backbuffer, NULL, location); +@@ -511,14 +511,14 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT + */ + if (!swapchain->render_to_fbo && render_to_fbo && wined3d_settings.offscreen_rendering_mode == ORM_FBO) + { +- surface_load_location(back_buffer, context, WINED3D_LOCATION_TEXTURE_RGB); ++ 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; + swapchain_update_draw_bindings(swapchain); + } + else + { +- surface_load_location(back_buffer, context, back_buffer->container->resource.draw_binding); ++ wined3d_resource_load_location(&back_buffer->resource, context, back_buffer->container->resource.draw_binding); + } + + if (swapchain->render_to_fbo) +@@ -640,7 +640,7 @@ void x11_copy_to_screen(const struct wined3d_swapchain *swapchain, const RECT *r + + TRACE("Copying surface %p to screen.\n", front); + +- surface_load_location(front, NULL, WINED3D_LOCATION_DIB); ++ wined3d_resource_load_location(&front->resource, NULL, WINED3D_LOCATION_DIB); + + src_dc = front->hDC; + window = swapchain->win_handle; +diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c +index ea9eacc..48717d7 100644 +--- a/dlls/wined3d/texture.c ++++ b/dlls/wined3d/texture.c +@@ -830,7 +830,7 @@ static void texture2d_sub_resource_add_dirty_region(struct wined3d_resource *sub + + surface_prepare_map_memory(surface); + context = context_acquire(surface->resource.device, NULL); +- surface_load_location(surface, context, surface->resource.map_binding); ++ wined3d_resource_load_location(&surface->resource, context, surface->resource.map_binding); + context_release(context); + wined3d_resource_invalidate_location(&surface->resource, ~surface->resource.map_binding); + } +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index b1e4cb6..059310b 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2358,8 +2358,6 @@ void surface_load(struct wined3d_surface *surface, struct wined3d_context *conte + 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) DECLSPEC_HIDDEN; +-void surface_load_location(struct wined3d_surface *surface, +- struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN; + void surface_modify_ds_location(struct wined3d_surface *surface, DWORD location, UINT w, UINT h) DECLSPEC_HIDDEN; + void surface_prepare_rb(struct wined3d_surface *surface, + const struct wined3d_gl_info *gl_info, BOOL multisample) DECLSPEC_HIDDEN; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0019-wined3d-Introduce-helper-functions-for-mapping-volum.patch b/patches/wined3d-CSMT_Main/0019-wined3d-Introduce-helper-functions-for-mapping-volum.patch new file mode 100644 index 00000000..8979f741 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0019-wined3d-Introduce-helper-functions-for-mapping-volum.patch @@ -0,0 +1,213 @@ +From 6502ec68de4a38d59a2e6690eca2546e710b6cbc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Wed, 18 Sep 2013 22:30:57 +0200 +Subject: wined3d: Introduce helper functions for mapping volumes. + +--- + dlls/wined3d/volume.c | 157 ++++++++++++++++++++++++++++++-------------------- + 1 file changed, 96 insertions(+), 61 deletions(-) + +diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c +index c93a1ef..ee64070 100644 +--- a/dlls/wined3d/volume.c ++++ b/dlls/wined3d/volume.c +@@ -475,12 +475,67 @@ static BOOL wined3d_volume_check_box_dimensions(const struct wined3d_volume *vol + return TRUE; + } + ++/* Context activation is done by the caller. */ ++static BOOL wined3d_volume_prepare_map_memory(struct wined3d_volume *volume, struct wined3d_context *context) ++{ ++ switch (volume->resource.map_binding) ++ { ++ case WINED3D_LOCATION_BUFFER: ++ wined3d_volume_prepare_pbo(volume, context); ++ return TRUE; ++ ++ case WINED3D_LOCATION_SYSMEM: ++ return volume_prepare_system_memory(volume); ++ ++ default: ++ ERR("Unexpected map binding %s.\n", wined3d_debug_location(volume->resource.map_binding)); ++ return FALSE; ++ } ++} ++ ++static BYTE *wined3d_volume_get_map_ptr(const struct wined3d_volume *volume, ++ const struct wined3d_context *context, DWORD flags) ++{ ++ const struct wined3d_gl_info *gl_info; ++ BYTE *ptr; ++ ++ switch (volume->resource.map_binding) ++ { ++ case WINED3D_LOCATION_BUFFER: ++ gl_info = context->gl_info; ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, volume->pbo)); ++ ++ if (gl_info->supported[ARB_MAP_BUFFER_RANGE]) ++ { ++ GLbitfield mapflags = wined3d_resource_gl_map_flags(flags); ++ mapflags &= ~GL_MAP_FLUSH_EXPLICIT_BIT; ++ ptr = GL_EXTCALL(glMapBufferRange(GL_PIXEL_UNPACK_BUFFER_ARB, ++ 0, volume->resource.size, mapflags)); ++ } ++ else ++ { ++ GLenum access = wined3d_resource_gl_legacy_map_flags(flags); ++ ptr = GL_EXTCALL(glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, access)); ++ } ++ ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); ++ checkGLcall("Map PBO"); ++ return ptr; ++ ++ case WINED3D_LOCATION_SYSMEM: ++ return volume->resource.heap_memory; ++ ++ default: ++ ERR("Unexpected map binding %s.\n", wined3d_debug_location(volume->resource.map_binding)); ++ return NULL; ++ } ++} ++ + HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume, + struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags) + { + 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; + +@@ -512,58 +567,22 @@ HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume, + + flags = wined3d_resource_sanitize_map_flags(&volume->resource, flags); + +- if (volume->resource.map_binding == WINED3D_LOCATION_BUFFER) ++ context = context_acquire(device, NULL); ++ if (!wined3d_volume_prepare_map_memory(volume, context)) + { +- context = context_acquire(device, NULL); +- gl_info = context->gl_info; +- +- wined3d_volume_prepare_pbo(volume, context); +- if (flags & WINED3D_MAP_DISCARD) +- wined3d_resource_validate_location(&volume->resource, WINED3D_LOCATION_BUFFER); +- else +- wined3d_resource_load_location(&volume->resource, context, WINED3D_LOCATION_BUFFER); +- +- GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 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_ARB, +- 0, volume->resource.size, mapflags)); +- } +- else +- { +- GLenum access = wined3d_resource_gl_legacy_map_flags(flags); +- base_memory = GL_EXTCALL(glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, access)); +- } +- +- GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); +- checkGLcall("Map PBO"); +- ++ WARN("Out of memory.\n"); ++ map_desc->data = NULL; + context_release(context); ++ return E_OUTOFMEMORY; + } ++ ++ if (flags & WINED3D_MAP_DISCARD) ++ wined3d_resource_validate_location(&volume->resource, volume->resource.map_binding); + else +- { +- if (!volume_prepare_system_memory(volume)) +- { +- WARN("Out of memory.\n"); +- map_desc->data = NULL; +- return E_OUTOFMEMORY; +- } ++ wined3d_resource_load_location(&volume->resource, context, volume->resource.map_binding); + +- if (flags & WINED3D_MAP_DISCARD) +- { +- wined3d_resource_validate_location(&volume->resource, WINED3D_LOCATION_SYSMEM); +- } +- else if (!(volume->resource.locations & WINED3D_LOCATION_SYSMEM)) +- { +- context = context_acquire(device, NULL); +- wined3d_resource_load_location(&volume->resource, context, WINED3D_LOCATION_SYSMEM); +- context_release(context); +- } +- base_memory = volume->resource.heap_memory; +- } ++ base_memory = wined3d_volume_get_map_ptr(volume, context, flags); ++ context_release(context); + + TRACE("Base memory pointer %p.\n", base_memory); + +@@ -621,8 +640,34 @@ struct wined3d_volume * CDECL wined3d_volume_from_resource(struct wined3d_resour + return volume_from_resource(resource); + } + ++static void wined3d_volume_release_map_ptr(const struct wined3d_volume *volume, ++ const struct wined3d_context *context) ++{ ++ const struct wined3d_gl_info *gl_info; ++ ++ switch (volume->resource.map_binding) ++ { ++ case WINED3D_LOCATION_BUFFER: ++ gl_info = context->gl_info; ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, volume->pbo)); ++ GL_EXTCALL(glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB)); ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); ++ checkGLcall("Unmap PBO"); ++ return; ++ ++ case WINED3D_LOCATION_SYSMEM: ++ return; ++ ++ default: ++ ERR("Unexpected map binding %s.\n", wined3d_debug_location(volume->resource.map_binding)); ++ return; ++ } ++} ++ + HRESULT CDECL wined3d_volume_unmap(struct wined3d_volume *volume) + { ++ struct wined3d_device *device = volume->resource.device; ++ struct wined3d_context *context; + TRACE("volume %p.\n", volume); + + if (!volume->resource.map_count) +@@ -631,19 +676,9 @@ HRESULT CDECL wined3d_volume_unmap(struct wined3d_volume *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(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, volume->pbo)); +- GL_EXTCALL(glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB)); +- GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); +- checkGLcall("Unmap PBO"); +- +- context_release(context); +- } ++ context = context_acquire(device, NULL); ++ wined3d_volume_release_map_ptr(volume, context); ++ context_release(context); + + volume->resource.map_count--; + +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0020-wined3d-Move-volume-PBO-infrastructure-into-the-reso.patch b/patches/wined3d-CSMT_Main/0020-wined3d-Move-volume-PBO-infrastructure-into-the-reso.patch new file mode 100644 index 00000000..791ce439 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0020-wined3d-Move-volume-PBO-infrastructure-into-the-reso.patch @@ -0,0 +1,311 @@ +From b416ab9ae21fee5c8253969318c55156c1d5fc0a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 16 Jan 2014 22:07:17 +0100 +Subject: wined3d: Move volume PBO infrastructure into the resource. + +--- + dlls/wined3d/resource.c | 64 +++++++++++++++++++++++++++++- + dlls/wined3d/volume.c | 90 +++++++----------------------------------- + dlls/wined3d/wined3d_private.h | 7 +++- + 3 files changed, 82 insertions(+), 79 deletions(-) + +diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c +index 63f8584..d904c36 100644 +--- a/dlls/wined3d/resource.c ++++ b/dlls/wined3d/resource.c +@@ -292,7 +292,7 @@ GLbitfield wined3d_resource_gl_map_flags(DWORD d3d_flags) + return ret; + } + +-GLenum wined3d_resource_gl_legacy_map_flags(DWORD d3d_flags) ++static GLenum wined3d_resource_gl_legacy_map_flags(DWORD d3d_flags) + { + if (d3d_flags & WINED3D_MAP_READONLY) + return GL_READ_ONLY_ARB; +@@ -398,6 +398,68 @@ void wined3d_resource_load_location(struct wined3d_resource *resource, + resource->resource_ops->resource_load_location(resource, context, location); + } + ++BYTE *wined3d_resource_get_map_ptr(const struct wined3d_resource *resource, ++ const struct wined3d_context *context, DWORD flags) ++{ ++ const struct wined3d_gl_info *gl_info; ++ BYTE *ptr; ++ ++ switch (resource->map_binding) ++ { ++ case WINED3D_LOCATION_BUFFER: ++ gl_info = context->gl_info; ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, resource->buffer_object)); ++ ++ if (gl_info->supported[ARB_MAP_BUFFER_RANGE]) ++ { ++ GLbitfield mapflags = wined3d_resource_gl_map_flags(flags); ++ mapflags &= ~GL_MAP_FLUSH_EXPLICIT_BIT; ++ ptr = GL_EXTCALL(glMapBufferRange(GL_PIXEL_UNPACK_BUFFER_ARB, ++ 0, resource->size, mapflags)); ++ } ++ else ++ { ++ GLenum access = wined3d_resource_gl_legacy_map_flags(flags); ++ ptr = GL_EXTCALL(glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, access)); ++ } ++ ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); ++ checkGLcall("Map GL buffer"); ++ return ptr; ++ ++ case WINED3D_LOCATION_SYSMEM: ++ return resource->heap_memory; ++ ++ default: ++ ERR("Unexpected map binding %s.\n", wined3d_debug_location(resource->map_binding)); ++ return NULL; ++ } ++} ++ ++void wined3d_resource_release_map_ptr(const struct wined3d_resource *resource, ++ const struct wined3d_context *context) ++{ ++ const struct wined3d_gl_info *gl_info; ++ ++ switch (resource->map_binding) ++ { ++ case WINED3D_LOCATION_BUFFER: ++ gl_info = context->gl_info; ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, resource->buffer_object)); ++ GL_EXTCALL(glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB)); ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); ++ checkGLcall("Unmap GL buffer"); ++ return; ++ ++ case WINED3D_LOCATION_SYSMEM: ++ return; ++ ++ default: ++ ERR("Unexpected map binding %s.\n", wined3d_debug_location(resource->map_binding)); ++ return; ++ } ++} ++ + void CDECL wined3d_resource_get_pitch(const struct wined3d_resource *resource, UINT *row_pitch, + UINT *slice_pitch) + { +diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c +index ee64070..1e03097 100644 +--- a/dlls/wined3d/volume.c ++++ b/dlls/wined3d/volume.c +@@ -215,7 +215,7 @@ static void wined3d_volume_load_location(struct wined3d_resource *resource, + } + else if (volume->resource.locations & WINED3D_LOCATION_BUFFER) + { +- struct wined3d_bo_address data = {volume->pbo, NULL}; ++ struct wined3d_bo_address data = {volume->resource.buffer_object, NULL}; + wined3d_volume_upload_data(volume, context, &data); + } + else if (volume->resource.locations & WINED3D_LOCATION_TEXTURE_RGB) +@@ -269,7 +269,7 @@ static void wined3d_volume_load_location(struct wined3d_resource *resource, + break; + + case WINED3D_LOCATION_BUFFER: +- if (!volume->pbo) ++ if (!volume->resource.buffer_object) + ERR("Trying to load WINED3D_LOCATION_BUFFER without setting it up first.\n"); + + if (volume->resource.locations & WINED3D_LOCATION_DISCARDED) +@@ -279,7 +279,7 @@ static void wined3d_volume_load_location(struct wined3d_resource *resource, + } + else if (volume->resource.locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) + { +- struct wined3d_bo_address data = {volume->pbo, NULL}; ++ struct wined3d_bo_address data = {volume->resource.buffer_object, NULL}; + + if (volume->resource.locations & WINED3D_LOCATION_TEXTURE_RGB) + wined3d_texture_bind_and_dirtify(volume->container, context, FALSE); +@@ -316,16 +316,16 @@ static void wined3d_volume_prepare_pbo(struct wined3d_volume *volume, struct win + { + const struct wined3d_gl_info *gl_info = context->gl_info; + +- if (volume->pbo) ++ if (volume->resource.buffer_object) + return; + +- GL_EXTCALL(glGenBuffersARB(1, &volume->pbo)); +- GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, volume->pbo)); ++ GL_EXTCALL(glGenBuffersARB(1, &volume->resource.buffer_object)); ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, volume->resource.buffer_object)); + GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, volume->resource.size, NULL, GL_STREAM_DRAW_ARB)); + GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); + checkGLcall("Create PBO"); + +- TRACE("Created PBO %u for volume %p.\n", volume->pbo, volume); ++ TRACE("Created PBO %u for volume %p.\n", volume->resource.buffer_object, volume); + } + + static void wined3d_volume_free_pbo(struct wined3d_volume *volume) +@@ -333,10 +333,10 @@ 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(glDeleteBuffersARB(1, &volume->pbo)); ++ TRACE("Deleting PBO %u belonging to volume %p.\n", volume->resource.buffer_object, volume); ++ GL_EXTCALL(glDeleteBuffersARB(1, &volume->resource.buffer_object)); + checkGLcall("glDeleteBuffersARB"); +- volume->pbo = 0; ++ volume->resource.buffer_object = 0; + context_release(context); + } + +@@ -344,7 +344,7 @@ void wined3d_volume_destroy(struct wined3d_volume *volume) + { + TRACE("volume %p.\n", volume); + +- if (volume->pbo) ++ if (volume->resource.buffer_object) + wined3d_volume_free_pbo(volume); + + resource_cleanup(&volume->resource); +@@ -377,7 +377,7 @@ static void volume_unload(struct wined3d_resource *resource) + wined3d_resource_invalidate_location(&volume->resource, ~WINED3D_LOCATION_DISCARDED); + } + +- if (volume->pbo) ++ if (volume->resource.buffer_object) + { + /* Should not happen because only dynamic default pool volumes + * have a buffer, and those are not evicted by device_evit_managed_resources +@@ -493,44 +493,6 @@ static BOOL wined3d_volume_prepare_map_memory(struct wined3d_volume *volume, str + } + } + +-static BYTE *wined3d_volume_get_map_ptr(const struct wined3d_volume *volume, +- const struct wined3d_context *context, DWORD flags) +-{ +- const struct wined3d_gl_info *gl_info; +- BYTE *ptr; +- +- switch (volume->resource.map_binding) +- { +- case WINED3D_LOCATION_BUFFER: +- gl_info = context->gl_info; +- GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, volume->pbo)); +- +- if (gl_info->supported[ARB_MAP_BUFFER_RANGE]) +- { +- GLbitfield mapflags = wined3d_resource_gl_map_flags(flags); +- mapflags &= ~GL_MAP_FLUSH_EXPLICIT_BIT; +- ptr = GL_EXTCALL(glMapBufferRange(GL_PIXEL_UNPACK_BUFFER_ARB, +- 0, volume->resource.size, mapflags)); +- } +- else +- { +- GLenum access = wined3d_resource_gl_legacy_map_flags(flags); +- ptr = GL_EXTCALL(glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, access)); +- } +- +- GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); +- checkGLcall("Map PBO"); +- return ptr; +- +- case WINED3D_LOCATION_SYSMEM: +- return volume->resource.heap_memory; +- +- default: +- ERR("Unexpected map binding %s.\n", wined3d_debug_location(volume->resource.map_binding)); +- return NULL; +- } +-} +- + HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume, + struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags) + { +@@ -581,7 +543,7 @@ HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume, + else + wined3d_resource_load_location(&volume->resource, context, volume->resource.map_binding); + +- base_memory = wined3d_volume_get_map_ptr(volume, context, flags); ++ base_memory = wined3d_resource_get_map_ptr(&volume->resource, context, flags); + context_release(context); + + TRACE("Base memory pointer %p.\n", base_memory); +@@ -640,30 +602,6 @@ struct wined3d_volume * CDECL wined3d_volume_from_resource(struct wined3d_resour + return volume_from_resource(resource); + } + +-static void wined3d_volume_release_map_ptr(const struct wined3d_volume *volume, +- const struct wined3d_context *context) +-{ +- const struct wined3d_gl_info *gl_info; +- +- switch (volume->resource.map_binding) +- { +- case WINED3D_LOCATION_BUFFER: +- gl_info = context->gl_info; +- GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, volume->pbo)); +- GL_EXTCALL(glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB)); +- GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); +- checkGLcall("Unmap PBO"); +- return; +- +- case WINED3D_LOCATION_SYSMEM: +- return; +- +- default: +- ERR("Unexpected map binding %s.\n", wined3d_debug_location(volume->resource.map_binding)); +- return; +- } +-} +- + HRESULT CDECL wined3d_volume_unmap(struct wined3d_volume *volume) + { + struct wined3d_device *device = volume->resource.device; +@@ -677,7 +615,7 @@ HRESULT CDECL wined3d_volume_unmap(struct wined3d_volume *volume) + } + + context = context_acquire(device, NULL); +- wined3d_volume_release_map_ptr(volume, context); ++ wined3d_resource_release_map_ptr(&volume->resource, context); + context_release(context); + + volume->resource.map_count--; +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 059310b..9285ab8 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2083,6 +2083,7 @@ struct wined3d_resource + UINT size; + DWORD priority; + void *heap_memory, *user_memory, *bitmap_data; ++ GLuint buffer_object; + UINT custom_row_pitch, custom_slice_pitch; + struct list resource_list_entry; + DWORD locations; +@@ -2113,12 +2114,15 @@ void resource_unload(struct wined3d_resource *resource) DECLSPEC_HIDDEN; + DWORD wined3d_resource_access_from_location(DWORD location) DECLSPEC_HIDDEN; + BOOL wined3d_resource_allocate_sysmem(struct wined3d_resource *resource) DECLSPEC_HIDDEN; + void wined3d_resource_free_sysmem(struct wined3d_resource *resource) DECLSPEC_HIDDEN; ++BYTE *wined3d_resource_get_map_ptr(const struct wined3d_resource *resource, ++ const struct wined3d_context *context, DWORD flags) 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; + void wined3d_resource_invalidate_location(struct wined3d_resource *resource, DWORD location) DECLSPEC_HIDDEN; + BOOL wined3d_resource_is_offscreen(struct wined3d_resource *resource) DECLSPEC_HIDDEN; + void wined3d_resource_load_location(struct wined3d_resource *resource, + struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN; ++void wined3d_resource_release_map_ptr(const struct wined3d_resource *resource, ++ const struct wined3d_context *context) 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; + void wined3d_resource_validate_location(struct wined3d_resource *resource, DWORD location) DECLSPEC_HIDDEN; +@@ -2248,7 +2252,6 @@ struct wined3d_volume + DWORD flags; + GLint texture_level; + DWORD download_count; +- GLuint pbo; + }; + + static inline struct wined3d_volume *volume_from_resource(struct wined3d_resource *resource) +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0021-wined3d-Remove-surface-pbo.patch b/patches/wined3d-CSMT_Main/0021-wined3d-Remove-surface-pbo.patch new file mode 100644 index 00000000..4ff42906 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0021-wined3d-Remove-surface-pbo.patch @@ -0,0 +1,160 @@ +From f6bb878818089d9f8f735ce5e2e4495f40ce7ec8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Tue, 21 Jan 2014 13:25:48 +0100 +Subject: wined3d: Remove surface->pbo. + +--- + dlls/wined3d/surface.c | 42 +++++++++++++++++++++--------------------- + dlls/wined3d/wined3d_private.h | 2 -- + 2 files changed, 21 insertions(+), 23 deletions(-) + +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 6154315..4a2b636 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -46,7 +46,7 @@ static void surface_cleanup(struct wined3d_surface *surface) + + TRACE("surface %p.\n", surface); + +- if (surface->pbo || surface->rb_multisample ++ if (surface->resource.buffer_object || surface->rb_multisample + || surface->rb_resolved || !list_empty(&surface->renderbuffers)) + { + struct wined3d_renderbuffer_entry *entry, *entry2; +@@ -56,10 +56,10 @@ static void surface_cleanup(struct wined3d_surface *surface) + context = context_acquire(surface->resource.device, NULL); + gl_info = context->gl_info; + +- if (surface->pbo) ++ if (surface->resource.buffer_object) + { +- TRACE("Deleting PBO %u.\n", surface->pbo); +- GL_EXTCALL(glDeleteBuffersARB(1, &surface->pbo)); ++ TRACE("Deleting PBO %u.\n", surface->resource.buffer_object); ++ GL_EXTCALL(glDeleteBuffersARB(1, &surface->resource.buffer_object)); + } + + if (surface->rb_multisample) +@@ -485,7 +485,7 @@ static void surface_get_memory(const struct wined3d_surface *surface, struct win + if (location & WINED3D_LOCATION_BUFFER) + { + data->addr = NULL; +- data->buffer_object = surface->pbo; ++ data->buffer_object = surface->resource.buffer_object; + return; + } + if (location & WINED3D_LOCATION_USER_MEMORY) +@@ -518,20 +518,20 @@ static void surface_prepare_buffer(struct wined3d_surface *surface) + GLenum error; + const struct wined3d_gl_info *gl_info; + +- if (surface->pbo) ++ if (surface->resource.buffer_object) + return; + + context = context_acquire(surface->resource.device, NULL); + gl_info = context->gl_info; + +- GL_EXTCALL(glGenBuffersARB(1, &surface->pbo)); ++ GL_EXTCALL(glGenBuffersARB(1, &surface->resource.buffer_object)); + error = gl_info->gl_ops.gl.p_glGetError(); +- if (!surface->pbo || error != GL_NO_ERROR) ++ if (!surface->resource.buffer_object || error != GL_NO_ERROR) + ERR("Failed to create a PBO with error %s (%#x).\n", debug_glerror(error), error); + +- TRACE("Binding PBO %u.\n", surface->pbo); ++ TRACE("Binding PBO %u.\n", surface->resource.buffer_object); + +- GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, surface->pbo)); ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, surface->resource.buffer_object)); + checkGLcall("glBindBufferARB"); + + GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, surface->resource.size + 4, +@@ -735,7 +735,7 @@ static void surface_unmap(struct wined3d_surface *surface) + context = context_acquire(device, NULL); + gl_info = context->gl_info; + +- GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, surface->pbo)); ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, surface->resource.buffer_object)); + GL_EXTCALL(glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB)); + GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); + checkGLcall("glUnmapBufferARB"); +@@ -1181,10 +1181,10 @@ HRESULT CDECL wined3d_surface_get_render_target_data(struct wined3d_surface *sur + /* Context activation is done by the caller. */ + static void surface_remove_pbo(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info) + { +- GL_EXTCALL(glDeleteBuffersARB(1, &surface->pbo)); +- checkGLcall("glDeleteBuffersARB(1, &surface->pbo)"); ++ GL_EXTCALL(glDeleteBuffersARB(1, &surface->resource.buffer_object)); ++ checkGLcall("glDeleteBuffersARB(1, &surface->resource.buffer_object)"); + +- surface->pbo = 0; ++ surface->resource.buffer_object = 0; + wined3d_resource_invalidate_location(&surface->resource, WINED3D_LOCATION_BUFFER); + } + +@@ -1241,7 +1241,7 @@ static void surface_unload(struct wined3d_resource *resource) + } + + /* Destroy PBOs, but load them into real sysmem before */ +- if (surface->pbo) ++ if (surface->resource.buffer_object) + surface_remove_pbo(surface, gl_info); + + /* Destroy fbo render buffers. This is needed for implicit render targets, for +@@ -2683,7 +2683,7 @@ HRESULT CDECL wined3d_surface_map(struct wined3d_surface *surface, + context = context_acquire(device, NULL); + gl_info = context->gl_info; + +- GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, surface->pbo)); ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, surface->resource.buffer_object)); + base_memory = GL_EXTCALL(glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_READ_WRITE_ARB)); + GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); + checkGLcall("map PBO"); +@@ -2774,7 +2774,7 @@ HRESULT CDECL wined3d_surface_getdc(struct wined3d_surface *surface, HDC *dc) + } + if (!(surface->resource.map_binding == WINED3D_LOCATION_USER_MEMORY + || surface->container->flags & WINED3D_TEXTURE_PIN_SYSMEM +- || surface->pbo)) ++ || surface->resource.buffer_object)) + surface->resource.map_binding = WINED3D_LOCATION_DIB; + } + +@@ -3055,9 +3055,9 @@ void flip_surface(struct wined3d_surface *front, struct wined3d_surface *back) + + /* Flip the PBO */ + { +- GLuint tmp_pbo = front->pbo; +- front->pbo = back->pbo; +- back->pbo = tmp_pbo; ++ GLuint tmp_pbo = front->resource.buffer_object; ++ front->resource.buffer_object = back->resource.buffer_object; ++ back->resource.buffer_object = tmp_pbo; + } + + /* Flip the opengl texture */ +@@ -4234,7 +4234,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + /* Don't use PBOs for converted surfaces. During PBO conversion we look at + * WINED3D_TEXTURE_CONVERTED but it isn't set (yet) in all cases it is + * getting called. */ +- if ((format.convert || conversion) && surface->pbo) ++ if ((format.convert || conversion) && surface->resource.buffer_object) + { + TRACE("Removing the pbo attached to surface %p.\n", surface); + +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 9285ab8..8dbee1a 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2310,8 +2310,6 @@ struct wined3d_surface + UINT pow2Width; + UINT pow2Height; + +- /* PBO */ +- GLuint pbo; + GLuint rb_multisample; + GLuint rb_resolved; + GLenum texture_target; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0022-wined3d-Use-resource-buffer-mapping-facilities-in-su.patch b/patches/wined3d-CSMT_Main/0022-wined3d-Use-resource-buffer-mapping-facilities-in-su.patch new file mode 100644 index 00000000..2b9112eb --- /dev/null +++ b/patches/wined3d-CSMT_Main/0022-wined3d-Use-resource-buffer-mapping-facilities-in-su.patch @@ -0,0 +1,177 @@ +From f3a0af1c19472f9af90881b17ffe0352285b5d64 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Tue, 21 Jan 2014 13:30:59 +0100 +Subject: wined3d: Use resource buffer mapping facilities in surfaces. + +--- + dlls/wined3d/resource.c | 8 +++++ + dlls/wined3d/surface.c | 78 ++++++++++--------------------------------------- + 2 files changed, 23 insertions(+), 63 deletions(-) + +diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c +index d904c36..c0e4d70 100644 +--- a/dlls/wined3d/resource.c ++++ b/dlls/wined3d/resource.c +@@ -430,6 +430,12 @@ BYTE *wined3d_resource_get_map_ptr(const struct wined3d_resource *resource, + case WINED3D_LOCATION_SYSMEM: + return resource->heap_memory; + ++ case WINED3D_LOCATION_DIB: ++ return resource->bitmap_data; ++ ++ case WINED3D_LOCATION_USER_MEMORY: ++ return resource->user_memory; ++ + default: + ERR("Unexpected map binding %s.\n", wined3d_debug_location(resource->map_binding)); + return NULL; +@@ -452,6 +458,8 @@ void wined3d_resource_release_map_ptr(const struct wined3d_resource *resource, + return; + + case WINED3D_LOCATION_SYSMEM: ++ case WINED3D_LOCATION_DIB: ++ case WINED3D_LOCATION_USER_MEMORY: + return; + + default: +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 4a2b636..4be6a50 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -716,36 +716,10 @@ static HRESULT surface_private_setup(struct wined3d_surface *surface) + + static void surface_unmap(struct wined3d_surface *surface) + { +- struct wined3d_device *device = surface->resource.device; +- const struct wined3d_gl_info *gl_info; +- struct wined3d_context *context; +- + TRACE("surface %p.\n", surface); + + memset(&surface->lockedRect, 0, sizeof(surface->lockedRect)); + +- switch (surface->resource.map_binding) +- { +- case WINED3D_LOCATION_SYSMEM: +- case WINED3D_LOCATION_USER_MEMORY: +- case WINED3D_LOCATION_DIB: +- break; +- +- case WINED3D_LOCATION_BUFFER: +- context = context_acquire(device, NULL); +- gl_info = context->gl_info; +- +- GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, surface->resource.buffer_object)); +- GL_EXTCALL(glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB)); +- GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); +- checkGLcall("glUnmapBufferARB"); +- context_release(context); +- break; +- +- default: +- ERR("Unexpected map binding %s.\n", wined3d_debug_location(surface->resource.map_binding)); +- } +- + if (surface->resource.locations & (WINED3D_LOCATION_DRAWABLE | WINED3D_LOCATION_TEXTURE_RGB)) + { + TRACE("Not dirtified, nothing to do.\n"); +@@ -2579,6 +2553,8 @@ struct wined3d_surface * CDECL wined3d_surface_from_resource(struct wined3d_reso + + HRESULT CDECL wined3d_surface_unmap(struct wined3d_surface *surface) + { ++ struct wined3d_device *device = surface->resource.device; ++ struct wined3d_context *context = NULL; + TRACE("surface %p.\n", surface); + + if (!surface->resource.map_count) +@@ -2588,6 +2564,12 @@ HRESULT CDECL wined3d_surface_unmap(struct wined3d_surface *surface) + } + --surface->resource.map_count; + ++ if (device->d3d_initialized) ++ context = context_acquire(device, NULL); ++ wined3d_resource_release_map_ptr(&surface->resource, context); ++ if (context) ++ context_release(context); ++ + surface->surface_ops->surface_unmap(surface); + + return WINED3D_OK; +@@ -2598,8 +2580,7 @@ HRESULT CDECL wined3d_surface_map(struct wined3d_surface *surface, + { + const struct wined3d_format *format = surface->resource.format; + struct wined3d_device *device = surface->resource.device; +- struct wined3d_context *context; +- const struct wined3d_gl_info *gl_info; ++ struct wined3d_context *context = NULL; + BYTE *base_memory; + + TRACE("surface %p, map_desc %p, rect %s, flags %#x.\n", +@@ -2641,6 +2622,9 @@ HRESULT CDECL wined3d_surface_map(struct wined3d_surface *surface, + } + } + ++ if (device->d3d_initialized) ++ context = context_acquire(device, NULL); ++ + surface_prepare_map_memory(surface); + if (flags & WINED3D_MAP_DISCARD) + { +@@ -2650,51 +2634,19 @@ HRESULT CDECL wined3d_surface_map(struct wined3d_surface *surface, + } + else + { +- struct wined3d_context *context = NULL; +- + if (surface->resource.usage & WINED3DUSAGE_DYNAMIC) + WARN_(d3d_perf)("Mapping a dynamic surface without WINED3D_MAP_DISCARD.\n"); + +- if (surface->resource.device->d3d_initialized) +- context = context_acquire(surface->resource.device, NULL); + wined3d_resource_load_location(&surface->resource, context, surface->resource.map_binding); +- if (context) +- context_release(context); + } + + if (!(flags & (WINED3D_MAP_NO_DIRTY_UPDATE | WINED3D_MAP_READONLY))) + wined3d_resource_invalidate_location(&surface->resource, ~surface->resource.map_binding); + +- switch (surface->resource.map_binding) +- { +- case WINED3D_LOCATION_SYSMEM: +- base_memory = surface->resource.heap_memory; +- break; +- +- case WINED3D_LOCATION_USER_MEMORY: +- base_memory = surface->resource.user_memory; +- break; +- +- case WINED3D_LOCATION_DIB: +- base_memory = surface->resource.bitmap_data; +- break; +- +- case WINED3D_LOCATION_BUFFER: +- context = context_acquire(device, NULL); +- gl_info = context->gl_info; ++ base_memory = wined3d_resource_get_map_ptr(&surface->resource, context, flags); + +- GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, surface->resource.buffer_object)); +- base_memory = GL_EXTCALL(glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_READ_WRITE_ARB)); +- GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); +- checkGLcall("map PBO"); +- +- context_release(context); +- break; +- +- default: +- ERR("Unexpected map binding %s.\n", wined3d_debug_location(surface->resource.map_binding)); +- base_memory = NULL; +- } ++ if (context) ++ context_release(context); + + if (format->flags & WINED3DFMT_FLAG_BROKEN_PITCH) + map_desc->row_pitch = surface->resource.width * format->byte_count; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0023-wined3d-Move-buffer-creation-into-the-resource.patch b/patches/wined3d-CSMT_Main/0023-wined3d-Move-buffer-creation-into-the-resource.patch new file mode 100644 index 00000000..bdbb0e72 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0023-wined3d-Move-buffer-creation-into-the-resource.patch @@ -0,0 +1,278 @@ +From df1b8896b325fb67b08f7cc8b6656d7166b451c2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Wed, 18 Sep 2013 22:49:34 +0200 +Subject: wined3d: Move buffer creation into the resource. + +More code from volume_unload can be moved to resource_unload eventually. +Before doing that, surfaces and buffers have to be migrated to the new +location scheme. Otherwise the unimplemented buffer_load_location and +surface_load_location will write a lot of ERRs. +--- + dlls/wined3d/resource.c | 66 ++++++++++++++++++++++++++++++++++++ + dlls/wined3d/texture.c | 2 +- + dlls/wined3d/volume.c | 76 ++---------------------------------------- + dlls/wined3d/wined3d_private.h | 4 ++- + 4 files changed, 72 insertions(+), 76 deletions(-) + +diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c +index c0e4d70..d5ec71f 100644 +--- a/dlls/wined3d/resource.c ++++ b/dlls/wined3d/resource.c +@@ -142,6 +142,18 @@ HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device * + return WINED3D_OK; + } + ++static void wined3d_resource_free_bo(struct wined3d_resource *resource) ++{ ++ struct wined3d_context *context = context_acquire(resource->device, NULL); ++ const struct wined3d_gl_info *gl_info = context->gl_info; ++ ++ TRACE("Deleting GL buffer %u belonging to resource %p.\n", resource->buffer_object, resource); ++ GL_EXTCALL(glDeleteBuffersARB(1, &resource->buffer_object)); ++ checkGLcall("glDeleteBuffersARB"); ++ resource->buffer_object = 0; ++ context_release(context); ++} ++ + void resource_cleanup(struct wined3d_resource *resource) + { + const struct wined3d *d3d = resource->device->wined3d; +@@ -154,6 +166,9 @@ void resource_cleanup(struct wined3d_resource *resource) + adapter_adjust_memory(resource->device->adapter, (INT64)0 - resource->size); + } + ++ if (resource->buffer_object) ++ wined3d_resource_free_bo(resource); ++ + wined3d_resource_free_sysmem(resource); + + device_resource_released(resource->device, resource); +@@ -164,6 +179,9 @@ void resource_unload(struct wined3d_resource *resource) + if (resource->map_count) + ERR("Resource %p is being unloaded while mapped.\n", resource); + ++ if (resource->buffer_object) ++ wined3d_resource_free_bo(resource); ++ + context_resource_unloaded(resource->device, + resource, resource->type); + } +@@ -468,6 +486,54 @@ void wined3d_resource_release_map_ptr(const struct wined3d_resource *resource, + } + } + ++/* Context activation is done by the caller. */ ++static void wined3d_resource_prepare_bo(struct wined3d_resource *resource, const struct wined3d_context *context) ++{ ++ const struct wined3d_gl_info *gl_info = context->gl_info; ++ ++ if (resource->buffer_object) ++ return; ++ ++ GL_EXTCALL(glGenBuffersARB(1, &resource->buffer_object)); ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, resource->buffer_object)); ++ GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, resource->size, NULL, GL_STREAM_DRAW_ARB)); ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); ++ checkGLcall("Create GL buffer"); ++ ++ TRACE("Created GL buffer %u for resource %p.\n", resource->buffer_object, resource); ++} ++ ++BOOL wined3d_resource_prepare_system_memory(struct wined3d_resource *resource) ++{ ++ if (resource->heap_memory) ++ return TRUE; ++ ++ if (!wined3d_resource_allocate_sysmem(resource)) ++ { ++ ERR("Failed to allocate system memory.\n"); ++ return FALSE; ++ } ++ return TRUE; ++} ++ ++/* Context activation is done by the caller. */ ++BOOL wined3d_resource_prepare_map_memory(struct wined3d_resource *resource, struct wined3d_context *context) ++{ ++ switch (resource->map_binding) ++ { ++ case WINED3D_LOCATION_BUFFER: ++ wined3d_resource_prepare_bo(resource, context); ++ return TRUE; ++ ++ case WINED3D_LOCATION_SYSMEM: ++ return wined3d_resource_prepare_system_memory(resource); ++ ++ default: ++ ERR("Unexpected map binding %s.\n", wined3d_debug_location(resource->map_binding)); ++ return FALSE; ++ } ++} ++ + void CDECL wined3d_resource_get_pitch(const struct wined3d_resource *resource, UINT *row_pitch, + UINT *slice_pitch) + { +diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c +index 48717d7..41cf61d 100644 +--- a/dlls/wined3d/texture.c ++++ b/dlls/wined3d/texture.c +@@ -1316,7 +1316,7 @@ static void texture3d_prepare_texture(struct wined3d_texture *texture, struct wi + void *mem = NULL; + + if (gl_info->supported[APPLE_CLIENT_STORAGE] && !format->convert +- && volume_prepare_system_memory(volume)) ++ && wined3d_resource_prepare_system_memory(&volume->resource)) + { + 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); +diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c +index 1e03097..a40d9f0 100644 +--- a/dlls/wined3d/volume.c ++++ b/dlls/wined3d/volume.c +@@ -27,19 +27,6 @@ + WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface); + WINE_DECLARE_DEBUG_CHANNEL(d3d_perf); + +-BOOL volume_prepare_system_memory(struct wined3d_volume *volume) +-{ +- if (volume->resource.heap_memory) +- return TRUE; +- +- if (!wined3d_resource_allocate_sysmem(&volume->resource)) +- { +- ERR("Failed to allocate system memory.\n"); +- return FALSE; +- } +- return TRUE; +-} +- + /* Context activation is done by the caller. */ + void wined3d_volume_upload_data(struct wined3d_volume *volume, const struct wined3d_context *context, + const struct wined3d_bo_address *data) +@@ -311,42 +298,10 @@ void wined3d_volume_load(struct wined3d_volume *volume, struct wined3d_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->resource.buffer_object) +- return; +- +- GL_EXTCALL(glGenBuffersARB(1, &volume->resource.buffer_object)); +- GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, volume->resource.buffer_object)); +- GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, volume->resource.size, NULL, GL_STREAM_DRAW_ARB)); +- GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); +- checkGLcall("Create PBO"); +- +- TRACE("Created PBO %u for volume %p.\n", volume->resource.buffer_object, 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->resource.buffer_object, volume); +- GL_EXTCALL(glDeleteBuffersARB(1, &volume->resource.buffer_object)); +- checkGLcall("glDeleteBuffersARB"); +- volume->resource.buffer_object = 0; +- context_release(context); +-} +- + void wined3d_volume_destroy(struct wined3d_volume *volume) + { + TRACE("volume %p.\n", volume); + +- if (volume->resource.buffer_object) +- wined3d_volume_free_pbo(volume); +- + resource_cleanup(&volume->resource); + volume->resource.parent_ops->wined3d_object_destroyed(volume->resource.parent); + HeapFree(GetProcessHeap(), 0, volume); +@@ -363,7 +318,7 @@ static void volume_unload(struct wined3d_resource *resource) + + TRACE("texture %p.\n", resource); + +- if (volume_prepare_system_memory(volume)) ++ if (wined3d_resource_prepare_system_memory(&volume->resource)) + { + context = context_acquire(device, NULL); + wined3d_resource_load_location(&volume->resource, context, WINED3D_LOCATION_SYSMEM); +@@ -377,15 +332,6 @@ static void volume_unload(struct wined3d_resource *resource) + wined3d_resource_invalidate_location(&volume->resource, ~WINED3D_LOCATION_DISCARDED); + } + +- if (volume->resource.buffer_object) +- { +- /* 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); +- } +- + /* The texture name is managed by the container. */ + volume->flags &= ~WINED3D_VFLAG_CLIENT_STORAGE; + +@@ -475,24 +421,6 @@ static BOOL wined3d_volume_check_box_dimensions(const struct wined3d_volume *vol + return TRUE; + } + +-/* Context activation is done by the caller. */ +-static BOOL wined3d_volume_prepare_map_memory(struct wined3d_volume *volume, struct wined3d_context *context) +-{ +- switch (volume->resource.map_binding) +- { +- case WINED3D_LOCATION_BUFFER: +- wined3d_volume_prepare_pbo(volume, context); +- return TRUE; +- +- case WINED3D_LOCATION_SYSMEM: +- return volume_prepare_system_memory(volume); +- +- default: +- ERR("Unexpected map binding %s.\n", wined3d_debug_location(volume->resource.map_binding)); +- return FALSE; +- } +-} +- + HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume, + struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags) + { +@@ -530,7 +458,7 @@ HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume, + flags = wined3d_resource_sanitize_map_flags(&volume->resource, flags); + + context = context_acquire(device, NULL); +- if (!wined3d_volume_prepare_map_memory(volume, context)) ++ if (!wined3d_resource_prepare_map_memory(&volume->resource, context)) + { + WARN("Out of memory.\n"); + map_desc->data = NULL; +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 8dbee1a..9353e57 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2121,6 +2121,9 @@ void wined3d_resource_invalidate_location(struct wined3d_resource *resource, DWO + BOOL wined3d_resource_is_offscreen(struct wined3d_resource *resource) DECLSPEC_HIDDEN; + void wined3d_resource_load_location(struct wined3d_resource *resource, + struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN; ++BOOL wined3d_resource_prepare_map_memory(struct wined3d_resource *resource, ++ struct wined3d_context *context) DECLSPEC_HIDDEN; ++BOOL wined3d_resource_prepare_system_memory(struct wined3d_resource *resource) DECLSPEC_HIDDEN; + void wined3d_resource_release_map_ptr(const struct wined3d_resource *resource, + const struct wined3d_context *context) DECLSPEC_HIDDEN; + DWORD wined3d_resource_sanitize_map_flags(const struct wined3d_resource *resource, DWORD flags) DECLSPEC_HIDDEN; +@@ -2259,7 +2262,6 @@ static inline struct wined3d_volume *volume_from_resource(struct wined3d_resourc + return CONTAINING_RECORD(resource, struct wined3d_volume, resource); + } + +-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; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0024-wined3d-Handle-WINED3D_LOCATION_DISCARDED-in-surface.patch b/patches/wined3d-CSMT_Main/0024-wined3d-Handle-WINED3D_LOCATION_DISCARDED-in-surface.patch new file mode 100644 index 00000000..ba3df109 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0024-wined3d-Handle-WINED3D_LOCATION_DISCARDED-in-surface.patch @@ -0,0 +1,31 @@ +From 34c2831af2c72f793ddb94da134f21f9cd613b5a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 19 Sep 2013 12:06:00 +0200 +Subject: wined3d: Handle WINED3D_LOCATION_DISCARDED in surface_load_texture. + +TODO: Move texture allocation to the caller, this way discarded locations can be handled in the resource. +--- + dlls/wined3d/surface.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 4be6a50..09bd72b 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -4091,6 +4091,13 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + POINT dst_point = {0, 0}; + BYTE *mem = NULL; + ++ if (surface->resource.locations & WINED3D_LOCATION_DISCARDED) ++ { ++ TRACE("Surface was discarded, nothing to do.\n"); ++ wined3d_texture_prepare_texture(texture, context, srgb); ++ return WINED3D_OK; ++ } ++ + if (wined3d_settings.offscreen_rendering_mode != ORM_FBO + && wined3d_resource_is_offscreen(&texture->resource) + && (surface->resource.locations & WINED3D_LOCATION_DRAWABLE)) +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0025-wined3d-Handle-LOCATION_DISCARDED-in-surface_load_dr.patch b/patches/wined3d-CSMT_Main/0025-wined3d-Handle-LOCATION_DISCARDED-in-surface_load_dr.patch new file mode 100644 index 00000000..7e95151e --- /dev/null +++ b/patches/wined3d-CSMT_Main/0025-wined3d-Handle-LOCATION_DISCARDED-in-surface_load_dr.patch @@ -0,0 +1,29 @@ +From 8f62fa5a9451ff5575e115758fcff80c7383aebe Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 19 Sep 2013 12:11:32 +0200 +Subject: wined3d: Handle LOCATION_DISCARDED in surface_load_drawable. + +--- + dlls/wined3d/surface.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 09bd72b..4a7e982 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -4062,6 +4062,12 @@ static HRESULT surface_load_drawable(struct wined3d_surface *surface, + { + RECT r; + ++ if (surface->resource.locations & WINED3D_LOCATION_DISCARDED) ++ { ++ TRACE("Surface was discarded, nothing to do.\n"); ++ return WINED3D_OK; ++ } ++ + if (wined3d_settings.offscreen_rendering_mode == ORM_FBO + && wined3d_resource_is_offscreen(&surface->container->resource)) + { +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0026-wined3d-Handle-WINED3D_LOCATION_DISCARDED-for-sysmem.patch b/patches/wined3d-CSMT_Main/0026-wined3d-Handle-WINED3D_LOCATION_DISCARDED-for-sysmem.patch new file mode 100644 index 00000000..503df570 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0026-wined3d-Handle-WINED3D_LOCATION_DISCARDED-for-sysmem.patch @@ -0,0 +1,75 @@ +From 73bc99a081af878150b2093f211239d44aab5444 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 19 Sep 2013 12:13:31 +0200 +Subject: wined3d: Handle WINED3D_LOCATION_DISCARDED for sysmem loads. + +--- + dlls/wined3d/resource.c | 12 ++++++++++++ + dlls/wined3d/volume.c | 14 ++------------ + 2 files changed, 14 insertions(+), 12 deletions(-) + +diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c +index d5ec71f..051297c 100644 +--- a/dlls/wined3d/resource.c ++++ b/dlls/wined3d/resource.c +@@ -397,6 +397,8 @@ void wined3d_resource_load_location(struct wined3d_resource *resource, + struct wined3d_context *context, DWORD location) + { + DWORD required_access = wined3d_resource_access_from_location(location); ++ DWORD simple_locations = WINED3D_LOCATION_SYSMEM | WINED3D_LOCATION_USER_MEMORY ++ | WINED3D_LOCATION_DIB | WINED3D_LOCATION_BUFFER; + + if ((resource->locations & location) == location) + { +@@ -409,6 +411,16 @@ void wined3d_resource_load_location(struct wined3d_resource *resource, + WARN("Operation requires %#x access, but resource only has %#x.\n", + required_access, resource->access_flags); + ++ if (location & simple_locations) ++ { ++ if (resource->locations & WINED3D_LOCATION_DISCARDED) ++ { ++ TRACE("Resource was discarded, nothing to do.\n"); ++ resource->locations |= location; ++ return; ++ } ++ } ++ + /* Context is NULL in ddraw-only operation without OpenGL. */ + if (!context) + ERR("A context is required for non-sysmem operation.\n"); +diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c +index a40d9f0..9ad7d75 100644 +--- a/dlls/wined3d/volume.c ++++ b/dlls/wined3d/volume.c +@@ -229,12 +229,7 @@ static void wined3d_volume_load_location(struct wined3d_resource *resource, + if (!volume->resource.heap_memory) + ERR("Trying to load WINED3D_LOCATION_SYSMEM without setting it up first.\n"); + +- if (volume->resource.locations & WINED3D_LOCATION_DISCARDED) +- { +- TRACE("Volume previously discarded, nothing to do.\n"); +- wined3d_resource_invalidate_location(&volume->resource, WINED3D_LOCATION_DISCARDED); +- } +- else if (volume->resource.locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) ++ if (volume->resource.locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) + { + struct wined3d_bo_address data = {0, volume->resource.heap_memory}; + +@@ -259,12 +254,7 @@ static void wined3d_volume_load_location(struct wined3d_resource *resource, + if (!volume->resource.buffer_object) + ERR("Trying to load WINED3D_LOCATION_BUFFER without setting it up first.\n"); + +- if (volume->resource.locations & WINED3D_LOCATION_DISCARDED) +- { +- TRACE("Volume previously discarded, nothing to do.\n"); +- wined3d_resource_invalidate_location(&volume->resource, WINED3D_LOCATION_DISCARDED); +- } +- else if (volume->resource.locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) ++ if (volume->resource.locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) + { + struct wined3d_bo_address data = {volume->resource.buffer_object, NULL}; + +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0027-wined3d-Discard-implicit-surfaces-on-unload.patch b/patches/wined3d-CSMT_Main/0027-wined3d-Discard-implicit-surfaces-on-unload.patch new file mode 100644 index 00000000..109a32fe --- /dev/null +++ b/patches/wined3d-CSMT_Main/0027-wined3d-Discard-implicit-surfaces-on-unload.patch @@ -0,0 +1,36 @@ +From 50e46931f38887d0164033482e502f90ef806ffd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Sat, 4 Jan 2014 13:20:25 +0100 +Subject: wined3d: Discard implicit surfaces on unload. + +--- + dlls/wined3d/surface.c | 13 +++---------- + 1 file changed, 3 insertions(+), 10 deletions(-) + +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 4a7e982..29f4563 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -1190,16 +1190,9 @@ static void surface_unload(struct wined3d_resource *resource) + /* Default pool resources are supposed to be destroyed before Reset is called. + * Implicit resources stay however. So this means we have an implicit render target + * or depth stencil. The content may be destroyed, but we still have to tear down +- * opengl resources, so we cannot leave early. +- * +- * Put the surfaces into sysmem, and reset the content. The D3D content is undefined, +- * but we can't set the sysmem INDRAWABLE because when we're rendering the swapchain +- * or the depth stencil into an FBO the texture or render buffer will be removed +- * and all flags get lost */ +- surface_prepare_system_memory(surface); +- memset(surface->resource.heap_memory, 0, surface->resource.size); +- wined3d_resource_validate_location(&surface->resource, WINED3D_LOCATION_SYSMEM); +- wined3d_resource_invalidate_location(&surface->resource, ~WINED3D_LOCATION_SYSMEM); ++ * opengl resources, so we cannot leave early. */ ++ wined3d_resource_validate_location(&surface->resource, WINED3D_LOCATION_DISCARDED); ++ wined3d_resource_invalidate_location(&surface->resource, ~WINED3D_LOCATION_DISCARDED); + + /* We also get here when the ddraw swapchain is destroyed, for example + * for a mode switch. In this case this surface won't necessarily be +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0028-wined3d-Don-t-try-to-flip-sysmem-copies-in-swapchain.patch b/patches/wined3d-CSMT_Main/0028-wined3d-Don-t-try-to-flip-sysmem-copies-in-swapchain.patch new file mode 100644 index 00000000..c9fb08a1 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0028-wined3d-Don-t-try-to-flip-sysmem-copies-in-swapchain.patch @@ -0,0 +1,73 @@ +From 33832b5fb0f7d3c8a0f93d4e3f3d7e1d4de0e6df Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 19 Sep 2013 13:08:33 +0200 +Subject: wined3d: Don't try to flip sysmem copies in swapchain_present. + +This was once an optimization for ddraw applications that mapped the +backbuffer to render movies. It doesn't work any more in the intended +fashion. +--- + dlls/wined3d/swapchain.c | 46 +++++++++------------------------------------- + 1 file changed, 9 insertions(+), 37 deletions(-) + +diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c +index e1a5b8a..05f68f7 100644 +--- a/dlls/wined3d/swapchain.c ++++ b/dlls/wined3d/swapchain.c +@@ -555,44 +555,16 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT + } + + front = surface_from_resource(wined3d_texture_get_sub_resource(swapchain->front_buffer, 0)); +- if (!swapchain->render_to_fbo && ((front->resource.locations & WINED3D_LOCATION_SYSMEM) +- || (back_buffer->resource.locations & WINED3D_LOCATION_SYSMEM))) ++ wined3d_resource_validate_location(&front->resource, WINED3D_LOCATION_DRAWABLE); ++ wined3d_resource_invalidate_location(&front->resource, ~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. If it is FLIP however, ++ * the texture / sysmem copy needs to be reloaded from the drawable. */ ++ if (swapchain->desc.swap_effect == WINED3D_SWAP_EFFECT_FLIP) + { +- /* Both memory copies of the surfaces are ok, flip them around too instead of dirtifying +- * Doesn't work with render_to_fbo because we're not flipping +- */ +- +- if (front->resource.size == back_buffer->resource.size) +- { +- flip_surface(front, back_buffer); +- +- /* Tell the front buffer surface that is has been modified. However, +- * the other locations were preserved during that, so keep the flags. +- * This serves to update the emulated overlay, if any. */ +- wined3d_resource_validate_location(&front->resource, WINED3D_LOCATION_DRAWABLE); +- } +- else +- { +- wined3d_resource_validate_location(&front->resource, WINED3D_LOCATION_DRAWABLE); +- wined3d_resource_invalidate_location(&front->resource, ~WINED3D_LOCATION_DRAWABLE); +- wined3d_resource_validate_location(&back_buffer->resource, WINED3D_LOCATION_DRAWABLE); +- wined3d_resource_invalidate_location(&back_buffer->resource, ~WINED3D_LOCATION_DRAWABLE); +- } +- } +- else +- { +- wined3d_resource_validate_location(&front->resource, WINED3D_LOCATION_DRAWABLE); +- wined3d_resource_invalidate_location(&front->resource, ~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. If it is FLIP however, +- * the texture / sysmem copy needs to be reloaded from the drawable +- */ +- if (swapchain->desc.swap_effect == WINED3D_SWAP_EFFECT_FLIP) +- { +- wined3d_resource_validate_location(&back_buffer->resource, back_buffer->container->resource.draw_binding); +- wined3d_resource_invalidate_location(&back_buffer->resource, ~back_buffer->container->resource.draw_binding); +- } ++ wined3d_resource_validate_location(&back_buffer->resource, back_buffer->container->resource.draw_binding); ++ wined3d_resource_invalidate_location(&back_buffer->resource, ~back_buffer->container->resource.draw_binding); + } + + if (fb->depth_stencil) +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0029-wined3d-Discard-the-backbuffer-in-discard-presents.patch b/patches/wined3d-CSMT_Main/0029-wined3d-Discard-the-backbuffer-in-discard-presents.patch new file mode 100644 index 00000000..4fad56d6 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0029-wined3d-Discard-the-backbuffer-in-discard-presents.patch @@ -0,0 +1,43 @@ +From bcd6f4338c70693ca49ce0775bdd08a2527db255 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 19 Sep 2013 13:09:58 +0200 +Subject: wined3d: Discard the backbuffer in discard presents. + +--- + dlls/wined3d/swapchain.c | 19 ++++++++++++------- + 1 file changed, 12 insertions(+), 7 deletions(-) + +diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c +index 05f68f7..dd7d2c7 100644 +--- a/dlls/wined3d/swapchain.c ++++ b/dlls/wined3d/swapchain.c +@@ -557,14 +557,19 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT + front = surface_from_resource(wined3d_texture_get_sub_resource(swapchain->front_buffer, 0)); + wined3d_resource_validate_location(&front->resource, WINED3D_LOCATION_DRAWABLE); + wined3d_resource_invalidate_location(&front->resource, ~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. If it is FLIP however, +- * the texture / sysmem copy needs to be reloaded from the drawable. */ +- if (swapchain->desc.swap_effect == WINED3D_SWAP_EFFECT_FLIP) ++ switch (swapchain->desc.swap_effect) + { +- wined3d_resource_validate_location(&back_buffer->resource, back_buffer->container->resource.draw_binding); +- wined3d_resource_invalidate_location(&back_buffer->resource, ~back_buffer->container->resource.draw_binding); ++ case WINED3D_SWAP_EFFECT_DISCARD: ++ wined3d_resource_validate_location(&back_buffer->resource, WINED3D_LOCATION_DISCARDED); ++ break; ++ ++ case WINED3D_SWAP_EFFECT_FLIP: ++ wined3d_resource_validate_location(&back_buffer->resource, back_buffer->container->resource.draw_binding); ++ wined3d_resource_invalidate_location(&back_buffer->resource, ~back_buffer->container->resource.draw_binding); ++ break; ++ ++ default: ++ break; + } + + if (fb->depth_stencil) +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0030-wined3d-Allocate-sysmem-for-client-storage-if-it-doe.patch b/patches/wined3d-CSMT_Main/0030-wined3d-Allocate-sysmem-for-client-storage-if-it-doe.patch new file mode 100644 index 00000000..1705916e --- /dev/null +++ b/patches/wined3d-CSMT_Main/0030-wined3d-Allocate-sysmem-for-client-storage-if-it-doe.patch @@ -0,0 +1,37 @@ +From d0f1f1278a8225075bd03c9586112bf29318563c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Mon, 16 Sep 2013 22:22:39 +0200 +Subject: wined3d: Allocate sysmem for client storage if it doesn't exist + already. + +--- + dlls/wined3d/texture.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c +index 41cf61d..8298e53 100644 +--- a/dlls/wined3d/texture.c ++++ b/dlls/wined3d/texture.c +@@ -904,8 +904,7 @@ static void texture2d_prepare_texture(struct wined3d_texture *texture, struct wi + if (gl_info->supported[APPLE_CLIENT_STORAGE]) + { + if (surface->flags & (SFLAG_NONPOW2 | SFLAG_DIBSECTION) +- || texture->flags & WINED3D_TEXTURE_CONVERTED +- || !surface->resource.heap_memory) ++ || texture->flags & WINED3D_TEXTURE_CONVERTED) + { + /* In some cases we want to disable client storage. + * SFLAG_NONPOW2 has a bigger opengl texture than the client memory, and different pitches +@@ -917,6 +916,9 @@ static void texture2d_prepare_texture(struct wined3d_texture *texture, struct wi + } + else + { ++ if (!surface->resource.heap_memory) ++ wined3d_resource_allocate_sysmem(&surface->resource); ++ + surface->flags |= SFLAG_CLIENT; + mem = surface->resource.heap_memory; + +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0031-wined3d-Introduce-a-function-to-retrieve-resource-me.patch b/patches/wined3d-CSMT_Main/0031-wined3d-Introduce-a-function-to-retrieve-resource-me.patch new file mode 100644 index 00000000..aae4bbfd --- /dev/null +++ b/patches/wined3d-CSMT_Main/0031-wined3d-Introduce-a-function-to-retrieve-resource-me.patch @@ -0,0 +1,159 @@ +From 564052d9ce2b7450a97ca3310d54d1b416976978 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Mon, 16 Sep 2013 22:44:33 +0200 +Subject: wined3d: Introduce a function to retrieve resource memory. + +--- + dlls/wined3d/resource.c | 30 ++++++++++++++++++++++++++++ + dlls/wined3d/surface.c | 45 ++++++------------------------------------ + dlls/wined3d/wined3d_private.h | 2 ++ + 3 files changed, 38 insertions(+), 39 deletions(-) + +diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c +index 051297c..94c06ac 100644 +--- a/dlls/wined3d/resource.c ++++ b/dlls/wined3d/resource.c +@@ -392,6 +392,36 @@ DWORD wined3d_resource_access_from_location(DWORD location) + } + } + ++void wined3d_resource_get_memory(const struct wined3d_resource *resource, ++ DWORD location, struct wined3d_bo_address *data) ++{ ++ if (location & WINED3D_LOCATION_BUFFER) ++ { ++ data->buffer_object = resource->buffer_object; ++ data->addr = NULL; ++ return; ++ } ++ if (location & WINED3D_LOCATION_USER_MEMORY) ++ { ++ data->buffer_object = 0; ++ data->addr = resource->user_memory; ++ return; ++ } ++ if (location & WINED3D_LOCATION_DIB) ++ { ++ data->buffer_object = 0; ++ data->addr = resource->bitmap_data; ++ return; ++ } ++ if (location & WINED3D_LOCATION_SYSMEM) ++ { ++ data->buffer_object = 0; ++ data->addr = resource->heap_memory; ++ return; ++ } ++ ERR("Unexpected location %s.\n", wined3d_debug_location(location)); ++} ++ + /* Context activation is optionally by the caller. Context may be NULL. */ + void wined3d_resource_load_location(struct wined3d_resource *resource, + struct wined3d_context *context, DWORD location) +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 29f4563..4815965 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -479,39 +479,6 @@ static HRESULT surface_create_dib_section(struct wined3d_surface *surface) + return WINED3D_OK; + } + +-static void surface_get_memory(const struct wined3d_surface *surface, struct wined3d_bo_address *data, +- DWORD location) +-{ +- if (location & WINED3D_LOCATION_BUFFER) +- { +- data->addr = NULL; +- data->buffer_object = surface->resource.buffer_object; +- return; +- } +- if (location & WINED3D_LOCATION_USER_MEMORY) +- { +- data->addr = surface->resource.user_memory; +- data->buffer_object = 0; +- return; +- } +- if (location & WINED3D_LOCATION_DIB) +- { +- data->addr = surface->resource.bitmap_data; +- data->buffer_object = 0; +- return; +- } +- if (location & WINED3D_LOCATION_SYSMEM) +- { +- data->addr = surface->resource.heap_memory; +- data->buffer_object = 0; +- return; +- } +- +- ERR("Unexpected locations %s.\n", wined3d_debug_location(location)); +- data->addr = NULL; +- data->buffer_object = 0; +-} +- + static void surface_prepare_buffer(struct wined3d_surface *surface) + { + struct wined3d_context *context; +@@ -1328,7 +1295,7 @@ static void surface_download_data(struct wined3d_surface *surface, const struct + return; + } + +- surface_get_memory(surface, &data, dst_location); ++ wined3d_resource_get_memory(&surface->resource, dst_location, &data); + + if (format->flags & WINED3DFMT_FLAG_COMPRESSED) + { +@@ -1694,7 +1661,7 @@ HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface, const P + wined3d_resource_load_location(&dst_surface->resource, context, WINED3D_LOCATION_TEXTURE_RGB); + wined3d_texture_bind(dst_surface->container, context, FALSE); + +- surface_get_memory(src_surface, &data, src_surface->resource.locations); ++ wined3d_resource_get_memory(&src_surface->resource, src_surface->resource.locations, &data); + wined3d_resource_get_pitch(&src_surface->resource, &src_row_pitch, &src_slice_pitch); + + surface_upload_data(dst_surface, gl_info, src_format, src_rect, src_row_pitch, dst_point, FALSE, &data); +@@ -2794,7 +2761,7 @@ static void read_from_framebuffer(struct wined3d_surface *surface, + BOOL srcIsUpsideDown; + struct wined3d_bo_address data; + +- surface_get_memory(surface, &data, dst_location); ++ wined3d_resource_get_memory(&surface->resource, dst_location, &data); + + /* Context_release does not restore the original context in case of + * nested context_acquire calls. Only read_from_framebuffer and +@@ -3986,8 +3953,8 @@ static void surface_copy_simple_location(struct wined3d_surface *surface, DWORD + struct wined3d_bo_address dst, src; + UINT size = surface->resource.size; + +- surface_get_memory(surface, &dst, location); +- surface_get_memory(surface, &src, surface->resource.locations); ++ wined3d_resource_get_memory(&surface->resource, location, &dst); ++ wined3d_resource_get_memory(&surface->resource, surface->resource.locations, &src); + + if (dst.buffer_object) + { +@@ -4206,7 +4173,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + surface_remove_pbo(surface, gl_info); + } + +- surface_get_memory(surface, &data, surface->resource.locations); ++ wined3d_resource_get_memory(&surface->resource, surface->resource.locations, &data); + if (format.convert) + { + /* This code is entered for texture formats which need a fixup. */ +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 9353e57..df2031a 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2116,6 +2116,8 @@ BOOL wined3d_resource_allocate_sysmem(struct wined3d_resource *resource) DECLSPE + void wined3d_resource_free_sysmem(struct wined3d_resource *resource) DECLSPEC_HIDDEN; + BYTE *wined3d_resource_get_map_ptr(const struct wined3d_resource *resource, + const struct wined3d_context *context, DWORD flags) DECLSPEC_HIDDEN; ++void wined3d_resource_get_memory(const struct wined3d_resource *resource, ++ DWORD location, struct wined3d_bo_address *data) DECLSPEC_HIDDEN; + GLbitfield wined3d_resource_gl_map_flags(DWORD d3d_flags) DECLSPEC_HIDDEN; + void wined3d_resource_invalidate_location(struct wined3d_resource *resource, DWORD location) DECLSPEC_HIDDEN; + BOOL wined3d_resource_is_offscreen(struct wined3d_resource *resource) DECLSPEC_HIDDEN; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0032-wined3d-Make-surface_ops-unmap-specific-for-front-bu.patch b/patches/wined3d-CSMT_Main/0032-wined3d-Make-surface_ops-unmap-specific-for-front-bu.patch new file mode 100644 index 00000000..3b7ee2a6 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0032-wined3d-Make-surface_ops-unmap-specific-for-front-bu.patch @@ -0,0 +1,116 @@ +From e13017df9a84b37e8452e16feebf5c5f06a132a8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 19 Sep 2013 13:36:00 +0200 +Subject: wined3d: Make surface_ops->unmap specific for front buffers. + +--- + dlls/wined3d/surface.c | 45 +++++++++++++++--------------------------- + dlls/wined3d/wined3d_private.h | 2 +- + 2 files changed, 17 insertions(+), 30 deletions(-) + +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 4815965..50d7e74 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -681,31 +681,22 @@ static HRESULT surface_private_setup(struct wined3d_surface *surface) + return WINED3D_OK; + } + +-static void surface_unmap(struct wined3d_surface *surface) ++static void surface_frontbuffer_updated(struct wined3d_surface *surface) + { +- TRACE("surface %p.\n", surface); +- +- memset(&surface->lockedRect, 0, sizeof(surface->lockedRect)); ++ struct wined3d_context *context = NULL; ++ struct wined3d_device *device = surface->resource.device; + +- if (surface->resource.locations & (WINED3D_LOCATION_DRAWABLE | WINED3D_LOCATION_TEXTURE_RGB)) ++ if (surface->resource.locations & WINED3D_LOCATION_DRAWABLE) + { + TRACE("Not dirtified, nothing to do.\n"); + return; + } + +- if (surface->container->swapchain && surface->container->swapchain->front_buffer == surface->container) +- { +- struct wined3d_device *device = surface->resource.device; +- struct wined3d_context *context = NULL; +- +- if (device->d3d_initialized) +- context = context_acquire(device, surface); +- wined3d_resource_load_location(&surface->resource, context, surface->container->resource.draw_binding); +- if (context) +- context_release(context); +- } +- else if (surface->resource.format->flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) +- FIXME("Depth / stencil buffer locking is not implemented.\n"); ++ if (device->d3d_initialized) ++ context = context_acquire(surface->resource.device, NULL); ++ wined3d_resource_load_location(&surface->resource, context, surface->container->resource.draw_binding); ++ if (context) ++ context_release(context); + } + + static BOOL surface_is_full_rect(const struct wined3d_surface *surface, const RECT *r) +@@ -1218,7 +1209,7 @@ static void wined3d_surface_location_invalidated(struct wined3d_resource *resour + static const struct wined3d_surface_ops surface_ops = + { + surface_private_setup, +- surface_unmap, ++ surface_frontbuffer_updated, + }; + + /***************************************************************************** +@@ -1262,21 +1253,15 @@ static HRESULT gdi_surface_private_setup(struct wined3d_surface *surface) + return WINED3D_OK; + } + +-static void gdi_surface_unmap(struct wined3d_surface *surface) ++static void gdi_surface_frontbuffer_updated(struct wined3d_surface *surface) + { +- TRACE("surface %p.\n", surface); +- +- /* Tell the swapchain to update the screen. */ +- if (surface->container->swapchain && surface->container == surface->container->swapchain->front_buffer) +- x11_copy_to_screen(surface->container->swapchain, &surface->lockedRect); +- +- memset(&surface->lockedRect, 0, sizeof(RECT)); ++ x11_copy_to_screen(surface->container->swapchain, &surface->lockedRect); + } + + static const struct wined3d_surface_ops gdi_surface_ops = + { + gdi_surface_private_setup, +- gdi_surface_unmap, ++ gdi_surface_frontbuffer_updated, + }; + + /* This call just downloads data, the caller is responsible for binding the +@@ -2530,7 +2515,9 @@ HRESULT CDECL wined3d_surface_unmap(struct wined3d_surface *surface) + if (context) + context_release(context); + +- surface->surface_ops->surface_unmap(surface); ++ if (surface->container->swapchain && surface->container == surface->container->swapchain->front_buffer) ++ surface->surface_ops->surface_frontbuffer_updated(surface); ++ memset(&surface->lockedRect, 0, sizeof(surface->lockedRect)); + + return WINED3D_OK; + } +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index df2031a..d69a581 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2300,7 +2300,7 @@ struct fbo_entry + struct wined3d_surface_ops + { + HRESULT (*surface_private_setup)(struct wined3d_surface *surface); +- void (*surface_unmap)(struct wined3d_surface *surface); ++ void (*surface_frontbuffer_updated)(struct wined3d_surface *surface); + }; + + struct wined3d_surface +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0033-wined3d-Move-check_block_align-to-resource.c.patch b/patches/wined3d-CSMT_Main/0033-wined3d-Move-check_block_align-to-resource.c.patch new file mode 100644 index 00000000..bc9d33b7 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0033-wined3d-Move-check_block_align-to-resource.c.patch @@ -0,0 +1,152 @@ +From 56c5228fce24415412c59b16744c1eab1fb6e038 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 19 Sep 2013 14:55:00 +0200 +Subject: wined3d: Move check_block_align to resource.c + +--- + dlls/wined3d/resource.c | 28 ++++++++++++++++++++++++++++ + dlls/wined3d/surface.c | 27 +++++++++++---------------- + dlls/wined3d/volume.c | 31 ++----------------------------- + dlls/wined3d/wined3d_private.h | 2 ++ + 4 files changed, 43 insertions(+), 45 deletions(-) + +diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c +index 94c06ac..947fe8d 100644 +--- a/dlls/wined3d/resource.c ++++ b/dlls/wined3d/resource.c +@@ -606,3 +606,31 @@ void CDECL wined3d_resource_get_pitch(const struct wined3d_resource *resource, U + + TRACE("Returning row pitch %u, slice pitch %u.\n", *row_pitch, *slice_pitch); + } ++ ++BOOL wined3d_resource_check_block_align(const struct wined3d_resource *resource, ++ const struct wined3d_box *box) ++{ ++ UINT width_mask, height_mask; ++ const struct wined3d_format *format = 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 != resource->width) ++ return FALSE; ++ if (box->bottom & height_mask && box->bottom != resource->height) ++ return FALSE; ++ ++ return TRUE; ++} +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 50d7e74..6fa2576 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -1531,23 +1531,18 @@ static void surface_upload_data(struct wined3d_surface *surface, const struct wi + + static BOOL surface_check_block_align(struct wined3d_surface *surface, const RECT *rect) + { +- UINT width_mask, height_mask; ++ struct wined3d_box box; + +- if (!rect->left && !rect->top +- && rect->right == surface->resource.width +- && rect->bottom == surface->resource.height) +- return TRUE; +- +- /* This assumes power of two block sizes, but NPOT block sizes would be +- * silly anyway. */ +- width_mask = surface->resource.format->block_width - 1; +- height_mask = surface->resource.format->block_height - 1; +- +- if (!(rect->left & width_mask) && !(rect->top & height_mask) +- && !(rect->right & width_mask) && !(rect->bottom & height_mask)) +- return TRUE; +- +- return FALSE; ++ if (!rect) ++ return wined3d_resource_check_block_align(&surface->resource, NULL); ++ ++ box.left = rect->left; ++ box.top = rect->top; ++ box.front = 0; ++ box.right = rect->right; ++ box.bottom = rect->bottom; ++ box.back = 1; ++ return wined3d_resource_check_block_align(&surface->resource, &box); + } + + HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface, const POINT *dst_point, +diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c +index 9ad7d75..c11c98c 100644 +--- a/dlls/wined3d/volume.c ++++ b/dlls/wined3d/volume.c +@@ -361,34 +361,6 @@ struct wined3d_resource * CDECL wined3d_volume_get_resource(struct wined3d_volum + return &volume->resource; + } + +-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; +-} +- + static BOOL wined3d_volume_check_box_dimensions(const struct wined3d_volume *volume, + const struct wined3d_box *box) + { +@@ -438,7 +410,8 @@ HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume, + WARN("Map box is invalid.\n"); + return WINED3DERR_INVALIDCALL; + } +- if ((format->flags & WINED3DFMT_FLAG_BLOCKS) && !volume_check_block_align(volume, box)) ++ if ((format->flags & WINED3DFMT_FLAG_BLOCKS) && ++ !wined3d_resource_check_block_align(&volume->resource, box)) + { + WARN("Map box is misaligned for %ux%u blocks.\n", + format->block_width, format->block_height); +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index d69a581..35f2445 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2113,6 +2113,8 @@ HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device * + void resource_unload(struct wined3d_resource *resource) DECLSPEC_HIDDEN; + DWORD wined3d_resource_access_from_location(DWORD location) DECLSPEC_HIDDEN; + BOOL wined3d_resource_allocate_sysmem(struct wined3d_resource *resource) DECLSPEC_HIDDEN; ++BOOL wined3d_resource_check_block_align(const struct wined3d_resource *resource, ++ const struct wined3d_box *box) DECLSPEC_HIDDEN; + void wined3d_resource_free_sysmem(struct wined3d_resource *resource) DECLSPEC_HIDDEN; + BYTE *wined3d_resource_get_map_ptr(const struct wined3d_resource *resource, + const struct wined3d_context *context, DWORD flags) DECLSPEC_HIDDEN; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0034-wined3d-Replace-surface-alloc-functions-with-resourc.patch b/patches/wined3d-CSMT_Main/0034-wined3d-Replace-surface-alloc-functions-with-resourc.patch new file mode 100644 index 00000000..339b76bd --- /dev/null +++ b/patches/wined3d-CSMT_Main/0034-wined3d-Replace-surface-alloc-functions-with-resourc.patch @@ -0,0 +1,230 @@ +From 86e9642f816e8f9bfa7b71f3157fd42071aaf7d6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Tue, 21 Jan 2014 16:40:56 +0100 +Subject: wined3d: Replace surface alloc functions with resource ones. + +--- + dlls/wined3d/resource.c | 10 +++++ + dlls/wined3d/surface.c | 91 ++++-------------------------------------- + dlls/wined3d/texture.c | 5 +-- + dlls/wined3d/wined3d_private.h | 1 - + 4 files changed, 20 insertions(+), 87 deletions(-) + +diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c +index 947fe8d..aa81c00 100644 +--- a/dlls/wined3d/resource.c ++++ b/dlls/wined3d/resource.c +@@ -570,6 +570,16 @@ BOOL wined3d_resource_prepare_map_memory(struct wined3d_resource *resource, stru + case WINED3D_LOCATION_SYSMEM: + return wined3d_resource_prepare_system_memory(resource); + ++ case WINED3D_LOCATION_USER_MEMORY: ++ if (!resource->user_memory) ++ ERR("Map binding is set to WINED3D_LOCATION_USER_MEMORY but resource->user_memory is NULL.\n"); ++ return TRUE; ++ ++ case WINED3D_LOCATION_DIB: ++ if (!resource->bitmap_data) ++ ERR("Map binding is set to WINED3D_LOCATION_DIB but resource->bitmap_data is NULL.\n"); ++ return TRUE; ++ + default: + ERR("Unexpected map binding %s.\n", wined3d_debug_location(resource->map_binding)); + return FALSE; +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 6fa2576..4c2a759 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -479,81 +479,6 @@ static HRESULT surface_create_dib_section(struct wined3d_surface *surface) + return WINED3D_OK; + } + +-static void surface_prepare_buffer(struct wined3d_surface *surface) +-{ +- struct wined3d_context *context; +- GLenum error; +- const struct wined3d_gl_info *gl_info; +- +- if (surface->resource.buffer_object) +- return; +- +- context = context_acquire(surface->resource.device, NULL); +- gl_info = context->gl_info; +- +- GL_EXTCALL(glGenBuffersARB(1, &surface->resource.buffer_object)); +- error = gl_info->gl_ops.gl.p_glGetError(); +- if (!surface->resource.buffer_object || error != GL_NO_ERROR) +- ERR("Failed to create a PBO with error %s (%#x).\n", debug_glerror(error), error); +- +- TRACE("Binding PBO %u.\n", surface->resource.buffer_object); +- +- GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, surface->resource.buffer_object)); +- checkGLcall("glBindBufferARB"); +- +- GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, surface->resource.size + 4, +- NULL, GL_STREAM_DRAW_ARB)); +- checkGLcall("glBufferDataARB"); +- +- GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); +- checkGLcall("glBindBufferARB"); +- +- context_release(context); +-} +- +-static void surface_prepare_system_memory(struct wined3d_surface *surface) +-{ +- TRACE("surface %p.\n", surface); +- +- if (surface->resource.heap_memory) +- return; +- +- /* Whatever surface we have, make sure that there is memory allocated +- * for the downloaded copy, or a PBO to map. */ +- if (!wined3d_resource_allocate_sysmem(&surface->resource)) +- ERR("Failed to allocate system memory.\n"); +- +- if (surface->resource.locations & WINED3D_LOCATION_SYSMEM) +- ERR("Surface without system memory has WINED3D_LOCATION_SYSMEM set.\n"); +-} +- +-void surface_prepare_map_memory(struct wined3d_surface *surface) +-{ +- switch (surface->resource.map_binding) +- { +- case WINED3D_LOCATION_SYSMEM: +- surface_prepare_system_memory(surface); +- break; +- +- case WINED3D_LOCATION_USER_MEMORY: +- if (!surface->resource.user_memory) +- ERR("Map binding is set to WINED3D_LOCATION_USER_MEMORY but surface->resource.user_memory is NULL.\n"); +- break; +- +- case WINED3D_LOCATION_DIB: +- if (!surface->resource.bitmap_data) +- ERR("Map binding is set to WINED3D_LOCATION_DIB but surface->resource.bitmap_data is NULL.\n"); +- break; +- +- case WINED3D_LOCATION_BUFFER: +- surface_prepare_buffer(surface); +- break; +- +- default: +- ERR("Unexpected map binding %s.\n", wined3d_debug_location(surface->resource.map_binding)); +- } +-} +- + static void surface_evict_sysmem(struct wined3d_surface *surface) + { + /* In some conditions the surface memory must not be freed: +@@ -1160,7 +1085,7 @@ static void surface_unload(struct wined3d_resource *resource) + } + else + { +- surface_prepare_map_memory(surface); ++ wined3d_resource_prepare_map_memory(&surface->resource, context); + wined3d_resource_load_location(&surface->resource, context, surface->resource.map_binding); + wined3d_resource_invalidate_location(&surface->resource, ~surface->resource.map_binding); + } +@@ -1780,7 +1705,7 @@ void surface_load(struct wined3d_surface *surface, struct wined3d_context *conte + /* To perform the color key conversion we need a sysmem copy of + * the surface. Make sure we have it. */ + +- surface_prepare_map_memory(surface); ++ wined3d_resource_prepare_map_memory(&surface->resource, context); + wined3d_resource_load_location(&surface->resource, context, surface->resource.map_binding); + wined3d_resource_invalidate_location(&surface->resource, ~surface->resource.map_binding); + /* Switching color keying on / off may change the internal format. */ +@@ -2164,7 +2089,7 @@ HRESULT wined3d_surface_update_desc(struct wined3d_surface *surface, + + if (!valid_location) + { +- surface_prepare_system_memory(surface); ++ wined3d_resource_prepare_system_memory(&surface->resource); + valid_location = WINED3D_LOCATION_SYSMEM; + } + +@@ -2567,7 +2492,7 @@ HRESULT CDECL wined3d_surface_map(struct wined3d_surface *surface, + if (device->d3d_initialized) + context = context_acquire(device, NULL); + +- surface_prepare_map_memory(surface); ++ wined3d_resource_prepare_map_memory(&surface->resource, context); + if (flags & WINED3D_MAP_DISCARD) + { + TRACE("WINED3D_MAP_DISCARD flag passed, marking %s as up to date.\n", +@@ -4097,7 +4022,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + { + /* Performance warning... */ + FIXME("Downloading RGB surface %p to reload it as sRGB.\n", surface); +- surface_prepare_map_memory(surface); ++ wined3d_resource_prepare_map_memory(&surface->resource, context); + wined3d_resource_load_location(&surface->resource, context, surface->resource.map_binding); + } + } +@@ -4108,7 +4033,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + { + /* Performance warning... */ + FIXME("Downloading sRGB surface %p to reload it as RGB.\n", surface); +- surface_prepare_map_memory(surface); ++ wined3d_resource_prepare_map_memory(&surface->resource, context); + wined3d_resource_load_location(&surface->resource, context, surface->resource.map_binding); + } + } +@@ -4117,7 +4042,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + { + WARN("Trying to load a texture from sysmem, but no simple location is valid.\n"); + /* Lets hope we get it from somewhere... */ +- surface_prepare_system_memory(surface); ++ wined3d_resource_prepare_system_memory(&surface->resource); + wined3d_resource_load_location(&surface->resource, context, WINED3D_LOCATION_SYSMEM); + } + +@@ -4150,7 +4075,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + else + surface->resource.map_binding = WINED3D_LOCATION_SYSMEM; + +- surface_prepare_map_memory(surface); ++ wined3d_resource_prepare_map_memory(&surface->resource, context); + wined3d_resource_load_location(&surface->resource, context, surface->resource.map_binding); + surface_remove_pbo(surface, gl_info); + } +diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c +index 8298e53..429eb89 100644 +--- a/dlls/wined3d/texture.c ++++ b/dlls/wined3d/texture.c +@@ -828,8 +828,8 @@ static void texture2d_sub_resource_add_dirty_region(struct wined3d_resource *sub + struct wined3d_surface *surface = surface_from_resource(sub_resource); + struct wined3d_context *context; + +- surface_prepare_map_memory(surface); + 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); +@@ -916,8 +916,7 @@ static void texture2d_prepare_texture(struct wined3d_texture *texture, struct wi + } + else + { +- if (!surface->resource.heap_memory) +- wined3d_resource_allocate_sysmem(&surface->resource); ++ wined3d_resource_prepare_system_memory(&surface->resource); + + surface->flags |= SFLAG_CLIENT; + mem = surface->resource.heap_memory; +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 35f2445..51c957b 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2380,7 +2380,6 @@ HRESULT wined3d_surface_create(struct wined3d_texture *container, const struct w + 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 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; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0035-wined3d-Don-t-delete-the-buffer-in-surface_cleanup.patch b/patches/wined3d-CSMT_Main/0035-wined3d-Don-t-delete-the-buffer-in-surface_cleanup.patch new file mode 100644 index 00000000..58a35ef5 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0035-wined3d-Don-t-delete-the-buffer-in-surface_cleanup.patch @@ -0,0 +1,29 @@ +From 900dc644b944426cf580aa03f236043322a1ac20 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Tue, 21 Jan 2014 16:41:33 +0100 +Subject: wined3d: Don't delete the buffer in surface_cleanup. + +--- + dlls/wined3d/surface.c | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 4c2a759..7d2d1ea 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -56,12 +56,6 @@ static void surface_cleanup(struct wined3d_surface *surface) + context = context_acquire(surface->resource.device, NULL); + gl_info = context->gl_info; + +- if (surface->resource.buffer_object) +- { +- TRACE("Deleting PBO %u.\n", surface->resource.buffer_object); +- GL_EXTCALL(glDeleteBuffersARB(1, &surface->resource.buffer_object)); +- } +- + if (surface->rb_multisample) + { + TRACE("Deleting multisample renderbuffer %u.\n", surface->rb_multisample); +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0036-wined3d-Use-resource-facilities-to-destroy-PBOs.patch b/patches/wined3d-CSMT_Main/0036-wined3d-Use-resource-facilities-to-destroy-PBOs.patch new file mode 100644 index 00000000..662ec6a4 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0036-wined3d-Use-resource-facilities-to-destroy-PBOs.patch @@ -0,0 +1,81 @@ +From 259e98f79a3de596a4fb79227180106c47423aa8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Tue, 21 Jan 2014 16:49:21 +0100 +Subject: wined3d: Use resource facilities to destroy PBOs. + +--- + dlls/wined3d/resource.c | 2 +- + dlls/wined3d/surface.c | 17 ++--------------- + dlls/wined3d/wined3d_private.h | 1 + + 3 files changed, 4 insertions(+), 16 deletions(-) + +diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c +index aa81c00..2a58a0c 100644 +--- a/dlls/wined3d/resource.c ++++ b/dlls/wined3d/resource.c +@@ -142,7 +142,7 @@ HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device * + return WINED3D_OK; + } + +-static void wined3d_resource_free_bo(struct wined3d_resource *resource) ++void wined3d_resource_free_bo(struct wined3d_resource *resource) + { + struct wined3d_context *context = context_acquire(resource->device, NULL); + const struct wined3d_gl_info *gl_info = context->gl_info; +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 7d2d1ea..91d9e59 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -1029,16 +1029,6 @@ HRESULT CDECL wined3d_surface_get_render_target_data(struct wined3d_surface *sur + return wined3d_surface_blt(surface, NULL, render_target, NULL, 0, NULL, WINED3D_TEXF_POINT); + } + +-/* Context activation is done by the caller. */ +-static void surface_remove_pbo(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info) +-{ +- GL_EXTCALL(glDeleteBuffersARB(1, &surface->resource.buffer_object)); +- checkGLcall("glDeleteBuffersARB(1, &surface->resource.buffer_object)"); +- +- surface->resource.buffer_object = 0; +- wined3d_resource_invalidate_location(&surface->resource, WINED3D_LOCATION_BUFFER); +-} +- + static ULONG surface_resource_incref(struct wined3d_resource *resource) + { + return wined3d_surface_incref(surface_from_resource(resource)); +@@ -1084,10 +1074,6 @@ static void surface_unload(struct wined3d_resource *resource) + wined3d_resource_invalidate_location(&surface->resource, ~surface->resource.map_binding); + } + +- /* Destroy PBOs, but load them into real sysmem before */ +- if (surface->resource.buffer_object) +- surface_remove_pbo(surface, gl_info); +- + /* Destroy fbo render buffers. This is needed for implicit render targets, for + * all application-created targets the application has to release the surface + * before calling _Reset +@@ -4071,7 +4057,8 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + + wined3d_resource_prepare_map_memory(&surface->resource, context); + wined3d_resource_load_location(&surface->resource, context, surface->resource.map_binding); +- surface_remove_pbo(surface, gl_info); ++ wined3d_resource_free_bo(&surface->resource); ++ wined3d_resource_invalidate_location(&surface->resource, WINED3D_LOCATION_BUFFER); + } + + wined3d_resource_get_memory(&surface->resource, surface->resource.locations, &data); +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 51c957b..81c9cfe 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2115,6 +2115,7 @@ DWORD wined3d_resource_access_from_location(DWORD location) DECLSPEC_HIDDEN; + BOOL wined3d_resource_allocate_sysmem(struct wined3d_resource *resource) DECLSPEC_HIDDEN; + BOOL wined3d_resource_check_block_align(const struct wined3d_resource *resource, + const struct wined3d_box *box) DECLSPEC_HIDDEN; ++void wined3d_resource_free_bo(struct wined3d_resource *resource) DECLSPEC_HIDDEN; + void wined3d_resource_free_sysmem(struct wined3d_resource *resource) DECLSPEC_HIDDEN; + BYTE *wined3d_resource_get_map_ptr(const struct wined3d_resource *resource, + const struct wined3d_context *context, DWORD flags) DECLSPEC_HIDDEN; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0037-wined3d-Move-simple-location-copying-to-the-resource.patch b/patches/wined3d-CSMT_Main/0037-wined3d-Move-simple-location-copying-to-the-resource.patch new file mode 100644 index 00000000..f793c9de --- /dev/null +++ b/patches/wined3d-CSMT_Main/0037-wined3d-Move-simple-location-copying-to-the-resource.patch @@ -0,0 +1,158 @@ +From 15497169d7c01aa9cbe051377b8e7088daacf2b3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Tue, 21 Jan 2014 16:58:08 +0100 +Subject: wined3d: Move simple location copying to the resource. + +--- + dlls/wined3d/resource.c | 38 ++++++++++++++++++++++++++++++++++++ + dlls/wined3d/surface.c | 51 ++++--------------------------------------------- + 2 files changed, 42 insertions(+), 47 deletions(-) + +diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c +index 2a58a0c..d9e2216 100644 +--- a/dlls/wined3d/resource.c ++++ b/dlls/wined3d/resource.c +@@ -423,6 +423,38 @@ void wined3d_resource_get_memory(const struct wined3d_resource *resource, + } + + /* Context activation is optionally by the caller. Context may be NULL. */ ++static void wined3d_resource_copy_simple_location(struct wined3d_resource *resource, ++ struct wined3d_context *context, DWORD location) ++{ ++ const struct wined3d_gl_info *gl_info; ++ struct wined3d_bo_address dst, src; ++ UINT size = resource->size; ++ ++ wined3d_resource_get_memory(resource, location, &dst); ++ wined3d_resource_get_memory(resource, resource->locations, &src); ++ ++ if (dst.buffer_object) ++ { ++ gl_info = context->gl_info; ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, dst.buffer_object)); ++ GL_EXTCALL(glBufferSubDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0, size, src.addr)); ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); ++ checkGLcall("Upload PBO"); ++ return; ++ } ++ if (src.buffer_object) ++ { ++ gl_info = context->gl_info; ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, src.buffer_object)); ++ GL_EXTCALL(glGetBufferSubDataARB(GL_PIXEL_PACK_BUFFER_ARB, 0, size, dst.addr)); ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0)); ++ checkGLcall("Download PBO"); ++ return; ++ } ++ memcpy(dst.addr, src.addr, size); ++} ++ ++/* Context activation is optionally by the caller. Context may be NULL. */ + void wined3d_resource_load_location(struct wined3d_resource *resource, + struct wined3d_context *context, DWORD location) + { +@@ -449,6 +481,12 @@ void wined3d_resource_load_location(struct wined3d_resource *resource, + resource->locations |= location; + return; + } ++ if (resource->locations & simple_locations) ++ { ++ wined3d_resource_copy_simple_location(resource, context, location); ++ resource->locations |= location; ++ return; ++ } + } + + /* Context is NULL in ddraw-only operation without OpenGL. */ +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 91d9e59..5b2359e 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -36,10 +36,6 @@ WINE_DECLARE_DEBUG_CHANNEL(d3d); + + #define MAXLOCKCOUNT 50 /* After this amount of locks do not free the sysmem copy. */ + +-static const DWORD surface_simple_locations = +- WINED3D_LOCATION_SYSMEM | WINED3D_LOCATION_USER_MEMORY +- | WINED3D_LOCATION_DIB | WINED3D_LOCATION_BUFFER; +- + static void surface_cleanup(struct wined3d_surface *surface) + { + struct wined3d_surface *overlay, *cur; +@@ -3832,54 +3828,12 @@ void surface_load_ds_location(struct wined3d_surface *surface, struct wined3d_co + surface->ds_current_size.cy = surface->resource.height; + } + +-static void surface_copy_simple_location(struct wined3d_surface *surface, DWORD location) +-{ +- struct wined3d_device *device = surface->resource.device; +- struct wined3d_context *context; +- const struct wined3d_gl_info *gl_info; +- struct wined3d_bo_address dst, src; +- UINT size = surface->resource.size; +- +- wined3d_resource_get_memory(&surface->resource, location, &dst); +- wined3d_resource_get_memory(&surface->resource, surface->resource.locations, &src); +- +- if (dst.buffer_object) +- { +- context = context_acquire(device, NULL); +- gl_info = context->gl_info; +- GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, dst.buffer_object)); +- GL_EXTCALL(glBufferSubDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0, size, src.addr)); +- GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); +- checkGLcall("Upload PBO"); +- context_release(context); +- return; +- } +- if (src.buffer_object) +- { +- context = context_acquire(device, NULL); +- gl_info = context->gl_info; +- GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, src.buffer_object)); +- GL_EXTCALL(glGetBufferSubDataARB(GL_PIXEL_PACK_BUFFER_ARB, 0, size, dst.addr)); +- GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0)); +- checkGLcall("Download PBO"); +- context_release(context); +- return; +- } +- memcpy(dst.addr, src.addr, size); +-} +- + /* Context activation is done by the caller. */ + static void surface_load_sysmem(struct wined3d_surface *surface, + struct wined3d_context *context, DWORD dst_location) + { + const struct wined3d_gl_info *gl_info = context->gl_info; + +- if (surface->resource.locations & surface_simple_locations) +- { +- surface_copy_simple_location(surface, dst_location); +- return; +- } +- + if (surface->resource.locations & (WINED3D_LOCATION_RB_MULTISAMPLE | WINED3D_LOCATION_RB_RESOLVED)) + wined3d_resource_load_location(&surface->resource, context, WINED3D_LOCATION_TEXTURE_RGB); + +@@ -3943,6 +3897,9 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + struct wined3d_format format; + POINT dst_point = {0, 0}; + BYTE *mem = NULL; ++ const DWORD simple_locations = ++ WINED3D_LOCATION_SYSMEM | WINED3D_LOCATION_USER_MEMORY ++ | WINED3D_LOCATION_DIB | WINED3D_LOCATION_BUFFER; + + if (surface->resource.locations & WINED3D_LOCATION_DISCARDED) + { +@@ -4018,7 +3975,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + } + } + +- if (!(surface->resource.locations & surface_simple_locations)) ++ if (!(surface->resource.locations & simple_locations)) + { + WARN("Trying to load a texture from sysmem, but no simple location is valid.\n"); + /* Lets hope we get it from somewhere... */ +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0038-wined3d-Move-most-of-volume_map-to-resource.c.patch b/patches/wined3d-CSMT_Main/0038-wined3d-Move-most-of-volume_map-to-resource.c.patch new file mode 100644 index 00000000..b3678d78 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0038-wined3d-Move-most-of-volume_map-to-resource.c.patch @@ -0,0 +1,294 @@ +From 9e47e310ee0c12e0793312777a1f170fcbd363f0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 19 Sep 2013 17:51:38 +0200 +Subject: wined3d: Move most of volume_map to resource.c + +The CPU access check can be moved once surfaces don't have to lock for +sysmem blits. Surfaces and volume have different block alignment and +boundary check behaviours. +--- + dlls/wined3d/resource.c | 114 +++++++++++++++++++++++++++++++++++++++++ + dlls/wined3d/volume.c | 101 +++--------------------------------- + dlls/wined3d/wined3d_private.h | 3 ++ + 3 files changed, 123 insertions(+), 95 deletions(-) + +diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c +index d9e2216..2443a9b 100644 +--- a/dlls/wined3d/resource.c ++++ b/dlls/wined3d/resource.c +@@ -682,3 +682,117 @@ BOOL wined3d_resource_check_block_align(const struct wined3d_resource *resource, + + return TRUE; + } ++ ++HRESULT wined3d_resource_map(struct wined3d_resource *resource, ++ struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags) ++{ ++ struct wined3d_device *device = resource->device; ++ struct wined3d_context *context = NULL; ++ BYTE *base_memory; ++ const struct wined3d_format *format = resource->format; ++ ++ TRACE("resource %p, map_desc %p, box %p, flags %#x.\n", ++ resource, map_desc, box, flags); ++ ++ if (resource->map_count) ++ { ++ WARN("Volume is already mapped.\n"); ++ return WINED3DERR_INVALIDCALL; ++ } ++ ++ flags = wined3d_resource_sanitize_map_flags(resource, flags); ++ ++ if (device->d3d_initialized) ++ context = context_acquire(device, NULL); ++ ++ if (!wined3d_resource_prepare_map_memory(resource, context)) ++ { ++ WARN("Out of memory.\n"); ++ map_desc->data = NULL; ++ context_release(context); ++ return E_OUTOFMEMORY; ++ } ++ ++ if (flags & WINED3D_MAP_DISCARD) ++ wined3d_resource_validate_location(resource, resource->map_binding); ++ else ++ wined3d_resource_load_location(resource, context, resource->map_binding); ++ ++ base_memory = wined3d_resource_get_map_ptr(resource, context, flags); ++ ++ if (context) ++ context_release(context); ++ ++ TRACE("Base memory pointer %p.\n", base_memory); ++ ++ if (format->flags & WINED3DFMT_FLAG_BROKEN_PITCH) ++ { ++ map_desc->row_pitch = resource->width * format->byte_count; ++ map_desc->slice_pitch = map_desc->row_pitch * resource->height; ++ } ++ else ++ { ++ wined3d_resource_get_pitch(resource, &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 ((format->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 * format->byte_count); ++ } ++ } ++ ++ if (!(flags & (WINED3D_MAP_NO_DIRTY_UPDATE | WINED3D_MAP_READONLY))) ++ wined3d_resource_invalidate_location(resource, ~resource->map_binding); ++ ++ 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_resource_unmap(struct wined3d_resource *resource) ++{ ++ struct wined3d_device *device = resource->device; ++ struct wined3d_context *context = NULL; ++ TRACE("resource %p.\n", resource); ++ ++ if (!resource->map_count) ++ { ++ WARN("Trying to unlock an unlocked resource %p.\n", resource); ++ return WINED3DERR_INVALIDCALL; ++ } ++ ++ if (device->d3d_initialized) ++ context = context_acquire(device, NULL); ++ wined3d_resource_release_map_ptr(resource, context); ++ if (context) ++ context_release(context); ++ ++ resource->map_count--; ++ ++ return WINED3D_OK; ++} +diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c +index c11c98c..7e5576b 100644 +--- a/dlls/wined3d/volume.c ++++ b/dlls/wined3d/volume.c +@@ -386,25 +386,15 @@ static BOOL wined3d_volume_check_box_dimensions(const struct wined3d_volume *vol + HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume, + struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags) + { +- struct wined3d_device *device = volume->resource.device; +- struct wined3d_context *context; +- BYTE *base_memory; ++ HRESULT hr; + const struct wined3d_format *format = volume->resource.format; + +- 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"); +@@ -418,74 +408,11 @@ HRESULT CDECL wined3d_volume_map(struct wined3d_volume *volume, + return WINED3DERR_INVALIDCALL; + } + +- flags = wined3d_resource_sanitize_map_flags(&volume->resource, flags); +- +- context = context_acquire(device, NULL); +- if (!wined3d_resource_prepare_map_memory(&volume->resource, context)) +- { +- WARN("Out of memory.\n"); +- map_desc->data = NULL; +- context_release(context); +- return E_OUTOFMEMORY; +- } +- +- if (flags & WINED3D_MAP_DISCARD) +- wined3d_resource_validate_location(&volume->resource, volume->resource.map_binding); +- else +- wined3d_resource_load_location(&volume->resource, context, volume->resource.map_binding); +- +- base_memory = wined3d_resource_get_map_ptr(&volume->resource, context, flags); +- context_release(context); +- +- TRACE("Base memory pointer %p.\n", base_memory); +- +- if (format->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_resource_get_pitch(&volume->resource, &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 ((format->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_resource_invalidate_location(&volume->resource, ~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); ++ hr = wined3d_resource_map(&volume->resource, map_desc, box, flags); ++ if (FAILED(hr)) ++ return hr; + +- return WINED3D_OK; ++ return hr; + } + + struct wined3d_volume * CDECL wined3d_volume_from_resource(struct wined3d_resource *resource) +@@ -495,23 +422,7 @@ struct wined3d_volume * CDECL wined3d_volume_from_resource(struct wined3d_resour + + HRESULT CDECL wined3d_volume_unmap(struct wined3d_volume *volume) + { +- struct wined3d_device *device = volume->resource.device; +- struct wined3d_context *context; +- TRACE("volume %p.\n", volume); +- +- if (!volume->resource.map_count) +- { +- WARN("Trying to unlock an unlocked volume %p.\n", volume); +- return WINED3DERR_INVALIDCALL; +- } +- +- context = context_acquire(device, NULL); +- wined3d_resource_release_map_ptr(&volume->resource, context); +- context_release(context); +- +- volume->resource.map_count--; +- +- return WINED3D_OK; ++ return wined3d_resource_unmap(&volume->resource); + } + + static ULONG volume_resource_incref(struct wined3d_resource *resource) +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 81c9cfe..43e1c21 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2126,12 +2126,15 @@ void wined3d_resource_invalidate_location(struct wined3d_resource *resource, DWO + BOOL wined3d_resource_is_offscreen(struct wined3d_resource *resource) DECLSPEC_HIDDEN; + void wined3d_resource_load_location(struct wined3d_resource *resource, + struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN; ++HRESULT wined3d_resource_map(struct wined3d_resource *resource, struct wined3d_map_desc *map_desc, ++ const struct wined3d_box *box, DWORD flags) DECLSPEC_HIDDEN; + BOOL wined3d_resource_prepare_map_memory(struct wined3d_resource *resource, + struct wined3d_context *context) DECLSPEC_HIDDEN; + BOOL wined3d_resource_prepare_system_memory(struct wined3d_resource *resource) DECLSPEC_HIDDEN; + void wined3d_resource_release_map_ptr(const struct wined3d_resource *resource, + const struct wined3d_context *context) DECLSPEC_HIDDEN; + DWORD wined3d_resource_sanitize_map_flags(const struct wined3d_resource *resource, DWORD flags) DECLSPEC_HIDDEN; ++HRESULT wined3d_resource_unmap(struct wined3d_resource *resource) DECLSPEC_HIDDEN; + void wined3d_resource_update_draw_binding(struct wined3d_resource *resource) DECLSPEC_HIDDEN; + void wined3d_resource_validate_location(struct wined3d_resource *resource, DWORD location) DECLSPEC_HIDDEN; + +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0039-wined3d-Use-resource_map-for-surface_map.patch b/patches/wined3d-CSMT_Main/0039-wined3d-Use-resource_map-for-surface_map.patch new file mode 100644 index 00000000..c45c3e33 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0039-wined3d-Use-resource_map-for-surface_map.patch @@ -0,0 +1,196 @@ +From 4f15b07cc64a3d364197a0ac73dd561c7b969183 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 19 Sep 2013 18:00:23 +0200 +Subject: wined3d: Use resource_map for surface_map. + +--- + dlls/wined3d/resource.c | 2 +- + dlls/wined3d/surface.c | 102 +++++++----------------------------------------- + dlls/wined3d/volume.c | 7 +++- + 3 files changed, 22 insertions(+), 89 deletions(-) + +diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c +index 2443a9b..8486dc3 100644 +--- a/dlls/wined3d/resource.c ++++ b/dlls/wined3d/resource.c +@@ -783,7 +783,7 @@ HRESULT wined3d_resource_unmap(struct wined3d_resource *resource) + if (!resource->map_count) + { + WARN("Trying to unlock an unlocked resource %p.\n", resource); +- return WINED3DERR_INVALIDCALL; ++ return WINEDDERR_NOTLOCKED; + } + + if (device->d3d_initialized) +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 5b2359e..16233d3 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -2394,46 +2394,25 @@ struct wined3d_surface * CDECL wined3d_surface_from_resource(struct wined3d_reso + + HRESULT CDECL wined3d_surface_unmap(struct wined3d_surface *surface) + { +- struct wined3d_device *device = surface->resource.device; +- struct wined3d_context *context = NULL; ++ HRESULT hr; + TRACE("surface %p.\n", surface); + +- if (!surface->resource.map_count) +- { +- WARN("Trying to unmap unmapped surface.\n"); +- return WINEDDERR_NOTLOCKED; +- } +- --surface->resource.map_count; +- +- if (device->d3d_initialized) +- context = context_acquire(device, NULL); +- wined3d_resource_release_map_ptr(&surface->resource, context); +- if (context) +- context_release(context); ++ hr = wined3d_resource_unmap(&surface->resource); ++ if (FAILED(hr)) ++ return hr; + + if (surface->container->swapchain && surface->container == surface->container->swapchain->front_buffer) + surface->surface_ops->surface_frontbuffer_updated(surface); + memset(&surface->lockedRect, 0, sizeof(surface->lockedRect)); + +- return WINED3D_OK; ++ return hr; + } + + HRESULT CDECL wined3d_surface_map(struct wined3d_surface *surface, + struct wined3d_map_desc *map_desc, const RECT *rect, DWORD flags) + { ++ struct wined3d_box box; + const struct wined3d_format *format = surface->resource.format; +- struct wined3d_device *device = surface->resource.device; +- struct wined3d_context *context = NULL; +- BYTE *base_memory; +- +- TRACE("surface %p, map_desc %p, rect %s, flags %#x.\n", +- surface, map_desc, wine_dbgstr_rect(rect), flags); +- +- if (surface->resource.map_count) +- { +- WARN("Surface is already mapped.\n"); +- return WINED3DERR_INVALIDCALL; +- } + + if ((format->flags & WINED3DFMT_FLAG_BLOCKS) && rect + && !surface_check_block_align(surface, rect)) +@@ -2445,11 +2424,6 @@ HRESULT CDECL wined3d_surface_map(struct wined3d_surface *surface, + return WINED3DERR_INVALIDCALL; + } + +- ++surface->resource.map_count; +- +- if (!(surface->resource.access_flags & WINED3D_RESOURCE_ACCESS_CPU)) +- WARN("Trying to lock unlockable surface.\n"); +- + /* Performance optimization: Count how often a surface is mapped, if it is + * mapped regularly do not throw away the system memory copy. This avoids + * the need to download the surface from OpenGL all the time. The surface +@@ -2465,72 +2439,26 @@ HRESULT CDECL wined3d_surface_map(struct wined3d_surface *surface, + } + } + +- if (device->d3d_initialized) +- context = context_acquire(device, NULL); +- +- wined3d_resource_prepare_map_memory(&surface->resource, context); +- if (flags & WINED3D_MAP_DISCARD) +- { +- TRACE("WINED3D_MAP_DISCARD flag passed, marking %s as up to date.\n", +- wined3d_debug_location(surface->resource.map_binding)); +- wined3d_resource_validate_location(&surface->resource, surface->resource.map_binding); +- } +- else ++ if (rect) + { +- if (surface->resource.usage & WINED3DUSAGE_DYNAMIC) +- WARN_(d3d_perf)("Mapping a dynamic surface without WINED3D_MAP_DISCARD.\n"); ++ surface->lockedRect = *rect; + +- wined3d_resource_load_location(&surface->resource, context, surface->resource.map_binding); ++ box.left = rect->left; ++ box.top = rect->top; ++ box.front = 0; ++ box.right = rect->right; ++ box.bottom = rect->bottom; ++ box.back = 1; + } +- +- if (!(flags & (WINED3D_MAP_NO_DIRTY_UPDATE | WINED3D_MAP_READONLY))) +- wined3d_resource_invalidate_location(&surface->resource, ~surface->resource.map_binding); +- +- base_memory = wined3d_resource_get_map_ptr(&surface->resource, context, flags); +- +- if (context) +- context_release(context); +- +- if (format->flags & WINED3DFMT_FLAG_BROKEN_PITCH) +- map_desc->row_pitch = surface->resource.width * format->byte_count; + else +- wined3d_resource_get_pitch(&surface->resource, &map_desc->row_pitch, &map_desc->slice_pitch); +- map_desc->slice_pitch = 0; +- +- if (!rect) + { +- map_desc->data = base_memory; + surface->lockedRect.left = 0; + surface->lockedRect.top = 0; + surface->lockedRect.right = surface->resource.width; + surface->lockedRect.bottom = surface->resource.height; + } +- else +- { +- if ((format->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 +- + ((rect->top / format->block_height) * map_desc->row_pitch) +- + ((rect->left / format->block_width) * format->block_byte_count); +- } +- else +- { +- map_desc->data = base_memory +- + (map_desc->row_pitch * rect->top) +- + (rect->left * format->byte_count); +- } +- surface->lockedRect.left = rect->left; +- surface->lockedRect.top = rect->top; +- surface->lockedRect.right = rect->right; +- surface->lockedRect.bottom = rect->bottom; +- } +- +- TRACE("Locked rect %s.\n", wine_dbgstr_rect(&surface->lockedRect)); +- TRACE("Returning memory %p, pitch %u.\n", map_desc->data, map_desc->row_pitch); + +- return WINED3D_OK; ++ return wined3d_resource_map(&surface->resource, map_desc, rect ? &box : NULL, flags); + } + + HRESULT CDECL wined3d_surface_getdc(struct wined3d_surface *surface, HDC *dc) +diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c +index 7e5576b..7ce5331 100644 +--- a/dlls/wined3d/volume.c ++++ b/dlls/wined3d/volume.c +@@ -422,7 +422,12 @@ struct wined3d_volume * CDECL wined3d_volume_from_resource(struct wined3d_resour + + HRESULT CDECL wined3d_volume_unmap(struct wined3d_volume *volume) + { +- return wined3d_resource_unmap(&volume->resource); ++ HRESULT hr; ++ ++ hr = wined3d_resource_unmap(&volume->resource); ++ if (hr == WINEDDERR_NOTLOCKED) ++ return WINED3DERR_INVALIDCALL; ++ return hr; + } + + static ULONG volume_resource_incref(struct wined3d_resource *resource) +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0040-wined3d-Use-client-storage-with-DIB-sections.patch b/patches/wined3d-CSMT_Main/0040-wined3d-Use-client-storage-with-DIB-sections.patch new file mode 100644 index 00000000..34b4f8e8 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0040-wined3d-Use-client-storage-with-DIB-sections.patch @@ -0,0 +1,78 @@ +From e2500c76e7b1b762eeb610d580ce90eec9798773 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Tue, 21 Jan 2014 17:06:20 +0100 +Subject: wined3d: Use client storage with DIB sections. + +Now that DIBs are a separate location, we can keep the sysmem around for +OpenGL's use. +--- + dlls/wined3d/surface.c | 27 --------------------------- + dlls/wined3d/texture.c | 3 +-- + 2 files changed, 1 insertion(+), 29 deletions(-) + +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 16233d3..303a0dc 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -484,28 +484,6 @@ static void surface_evict_sysmem(struct wined3d_surface *surface) + wined3d_resource_invalidate_location(&surface->resource, WINED3D_LOCATION_SYSMEM); + } + +-static void surface_release_client_storage(struct wined3d_surface *surface) +-{ +- struct wined3d_context *context = context_acquire(surface->resource.device, NULL); +- const struct wined3d_gl_info *gl_info = context->gl_info; +- +- if (surface->container->texture_rgb.name) +- { +- wined3d_texture_bind_and_dirtify(surface->container, context, FALSE); +- gl_info->gl_ops.gl.p_glTexImage2D(surface->texture_target, surface->texture_level, +- GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); +- } +- if (surface->container->texture_srgb.name) +- { +- wined3d_texture_bind_and_dirtify(surface->container, context, TRUE); +- gl_info->gl_ops.gl.p_glTexImage2D(surface->texture_target, surface->texture_level, +- GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); +- } +- wined3d_texture_force_reload(surface->container); +- +- context_release(context); +-} +- + static BOOL surface_use_pbo(const struct wined3d_surface *surface) + { + const struct wined3d_gl_info *gl_info = &surface->resource.device->adapter->gl_info; +@@ -2483,11 +2461,6 @@ HRESULT CDECL wined3d_surface_getdc(struct wined3d_surface *surface, HDC *dc) + /* Create a DIB section if there isn't a dc yet. */ + if (!surface->hDC) + { +- if (surface->flags & SFLAG_CLIENT) +- { +- wined3d_resource_load_location(&surface->resource, context, WINED3D_LOCATION_SYSMEM); +- surface_release_client_storage(surface); +- } + hr = surface_create_dib_section(surface); + if (FAILED(hr)) + { +diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c +index 429eb89..ec5c847 100644 +--- a/dlls/wined3d/texture.c ++++ b/dlls/wined3d/texture.c +@@ -903,12 +903,11 @@ static void texture2d_prepare_texture(struct wined3d_texture *texture, struct wi + + if (gl_info->supported[APPLE_CLIENT_STORAGE]) + { +- if (surface->flags & (SFLAG_NONPOW2 | SFLAG_DIBSECTION) ++ if (surface->flags & (SFLAG_NONPOW2) + || texture->flags & WINED3D_TEXTURE_CONVERTED) + { + /* 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 + */ +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0041-wined3d-Don-t-call-the-public-map-function-in-surfac.patch b/patches/wined3d-CSMT_Main/0041-wined3d-Don-t-call-the-public-map-function-in-surfac.patch new file mode 100644 index 00000000..9514536a --- /dev/null +++ b/patches/wined3d-CSMT_Main/0041-wined3d-Don-t-call-the-public-map-function-in-surfac.patch @@ -0,0 +1,101 @@ +From 89a2597787017d7bc966c2a146fa4c4fc59e9ebb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Mon, 23 Sep 2013 23:58:41 +0200 +Subject: wined3d: Don't call the public map function in + surface_convert_format. + +TODO: Creating a helper surface and releasing it won't work with the CS. +surface_cpu_blt will be called via the CS, so it can't call external +methods that enqueue commands in the stream. +--- + dlls/wined3d/surface.c | 57 +++++++++++++++++++++++++++++++++----------------- + 1 file changed, 38 insertions(+), 19 deletions(-) + +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 303a0dc..045ede5 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -2253,11 +2253,14 @@ static inline const struct d3dfmt_converter_desc *find_converter(enum wined3d_fo + + static struct wined3d_texture *surface_convert_format(struct wined3d_surface *source, enum wined3d_format_id to_fmt) + { +- struct wined3d_map_desc src_map, dst_map; ++ void *dst_data = NULL, *src_data = NULL; ++ UINT src_row_pitch, src_slice_pitch, dst_row_pitch, dst_slice_pitch; + const struct d3dfmt_converter_desc *conv; + struct wined3d_texture *ret = NULL; + struct wined3d_resource_desc desc; + struct wined3d_surface *dst; ++ struct wined3d_context *context = NULL; ++ struct wined3d_device *device = source->resource.device; + + conv = find_converter(source->resource.format->id, to_fmt); + if (!conv) +@@ -2281,30 +2284,46 @@ static struct wined3d_texture *surface_convert_format(struct wined3d_surface *so + } + dst = surface_from_resource(wined3d_texture_get_sub_resource(ret, 0)); + +- memset(&src_map, 0, sizeof(src_map)); +- memset(&dst_map, 0, sizeof(dst_map)); ++ wined3d_resource_get_pitch(&source->resource, &src_row_pitch, &src_slice_pitch); ++ wined3d_resource_get_pitch(&ret->resource, &dst_row_pitch, &dst_slice_pitch); + +- if (FAILED(wined3d_surface_map(source, &src_map, NULL, WINED3D_MAP_READONLY))) +- { +- ERR("Failed to lock the source surface.\n"); +- wined3d_texture_decref(ret); +- return NULL; +- } +- if (FAILED(wined3d_surface_map(dst, &dst_map, NULL, 0))) +- { +- ERR("Failed to lock the destination surface.\n"); +- wined3d_surface_unmap(source); +- wined3d_texture_decref(ret); +- return NULL; +- } ++ if (device->d3d_initialized) ++ context = context_acquire(device, NULL); ++ ++ wined3d_resource_load_location(&source->resource, context, source->resource.map_binding); ++ src_data = wined3d_resource_get_map_ptr(&source->resource, context, WINED3D_MAP_READONLY); ++ if (!src_data) ++ goto error; + +- conv->convert(src_map.data, dst_map.data, src_map.row_pitch, dst_map.row_pitch, ++ if (!wined3d_resource_prepare_map_memory(&dst->resource, context)) ++ goto error; ++ dst_data = wined3d_resource_get_map_ptr(&dst->resource, context, 0); ++ if (!dst_data) ++ goto error; ++ ++ conv->convert(src_data, dst_data, src_row_pitch, dst_row_pitch, + source->resource.width, source->resource.height); + +- wined3d_surface_unmap(dst); +- wined3d_surface_unmap(source); ++ wined3d_resource_release_map_ptr(&dst->resource, context); ++ wined3d_resource_release_map_ptr(&source->resource, context); ++ ++ if (context) ++ context_release(context); + + return ret; ++ ++error: ++ ERR("Surface conversion failed.\n"); ++ ++ if (src_data) ++ wined3d_resource_release_map_ptr(&source->resource, context); ++ if (dst_data) ++ wined3d_resource_release_map_ptr(&ret->resource, context); ++ if (ret) ++ wined3d_texture_decref(ret); ++ if (context) ++ context_release(context); ++ return NULL; + } + + static HRESULT _Blt_ColorFill(BYTE *buf, unsigned int width, unsigned int height, +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0042-wined3d-Don-t-call-the-public-map-function-in-surfac.patch b/patches/wined3d-CSMT_Main/0042-wined3d-Don-t-call-the-public-map-function-in-surfac.patch new file mode 100644 index 00000000..779f572e --- /dev/null +++ b/patches/wined3d-CSMT_Main/0042-wined3d-Don-t-call-the-public-map-function-in-surfac.patch @@ -0,0 +1,292 @@ +From fa6437785e10e647df1af29b1ac544d2d1f3466f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Tue, 24 Sep 2013 00:31:39 +0200 +Subject: wined3d: Don't call the public map function in surface_cpu_blt. + +--- + dlls/wined3d/surface.c | 111 ++++++++++++++++++++++++++++++++----------------- + 1 file changed, 74 insertions(+), 37 deletions(-) + +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 045ede5..3702866 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -4359,21 +4359,36 @@ static HRESULT surface_cpu_blt(struct wined3d_surface *dst_surface, const RECT * + int bpp, srcheight, srcwidth, dstheight, dstwidth, width; + const struct wined3d_format *src_format, *dst_format; + struct wined3d_texture *src_texture = NULL; +- struct wined3d_map_desc dst_map, src_map; ++ void *src_data = NULL, *dst_data = NULL; ++ UINT src_row_pitch, src_slice_pitch, dst_row_pitch, dst_slice_pitch; + const BYTE *sbase = NULL; + HRESULT hr = WINED3D_OK; + const BYTE *sbuf; + BYTE *dbuf; + int x, y; ++ struct wined3d_device *device = dst_surface->resource.device; ++ struct wined3d_context *context = NULL; + + TRACE("dst_surface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p, filter %s.\n", + dst_surface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), + flags, fx, debug_d3dtexturefiltertype(filter)); + ++ if (device->d3d_initialized) ++ context = context_acquire(device, NULL); ++ ++ if (!wined3d_resource_prepare_map_memory(&dst_surface->resource, context)) ++ { ++ hr = E_OUTOFMEMORY; ++ goto error; ++ } ++ wined3d_resource_load_location(&dst_surface->resource, context, dst_surface->resource.map_binding); ++ + if (src_surface == dst_surface) + { +- wined3d_surface_map(dst_surface, &dst_map, NULL, 0); +- src_map = dst_map; ++ dst_data = wined3d_resource_get_map_ptr(&dst_surface->resource, context, 0); ++ wined3d_resource_get_pitch(&dst_surface->resource, &dst_row_pitch, &dst_slice_pitch); ++ src_data = dst_data; ++ src_row_pitch = dst_row_pitch; + src_format = dst_surface->resource.format; + dst_format = src_format; + } +@@ -4382,6 +4397,12 @@ static HRESULT surface_cpu_blt(struct wined3d_surface *dst_surface, const RECT * + dst_format = dst_surface->resource.format; + if (src_surface) + { ++ if (!wined3d_resource_prepare_map_memory(&src_surface->resource, context)) ++ { ++ hr = E_OUTOFMEMORY; ++ goto error; ++ } ++ + if (dst_surface->resource.format->id != src_surface->resource.format->id) + { + if (!(src_texture = surface_convert_format(src_surface, dst_format->id))) +@@ -4392,7 +4413,9 @@ static HRESULT surface_cpu_blt(struct wined3d_surface *dst_surface, const RECT * + } + src_surface = surface_from_resource(wined3d_texture_get_sub_resource(src_texture, 0)); + } +- wined3d_surface_map(src_surface, &src_map, NULL, WINED3D_MAP_READONLY); ++ wined3d_resource_load_location(&src_surface->resource, context, src_surface->resource.map_binding); ++ wined3d_resource_get_pitch(&src_surface->resource, &src_row_pitch, &src_slice_pitch); ++ src_data = wined3d_resource_get_map_ptr(&src_surface->resource, context, 0); + src_format = src_surface->resource.format; + } + else +@@ -4400,7 +4423,8 @@ static HRESULT surface_cpu_blt(struct wined3d_surface *dst_surface, const RECT * + src_format = dst_format; + } + +- wined3d_surface_map(dst_surface, &dst_map, dst_rect, 0); ++ wined3d_resource_get_pitch(&dst_surface->resource, &dst_row_pitch, &dst_slice_pitch); ++ dst_data = wined3d_resource_get_map_ptr(&dst_surface->resource, context, 0); + } + + bpp = dst_surface->resource.format->byte_count; +@@ -4411,15 +4435,12 @@ static HRESULT surface_cpu_blt(struct wined3d_surface *dst_surface, const RECT * + width = (dst_rect->right - dst_rect->left) * bpp; + + if (src_surface) +- sbase = (BYTE *)src_map.data +- + ((src_rect->top / src_format->block_height) * src_map.row_pitch) ++ sbase = (BYTE *)src_data ++ + ((src_rect->top / src_format->block_height) * src_row_pitch) + + ((src_rect->left / src_format->block_width) * src_format->block_byte_count); +- if (src_surface != dst_surface) +- dbuf = dst_map.data; +- else +- dbuf = (BYTE *)dst_map.data +- + ((dst_rect->top / dst_format->block_height) * dst_map.row_pitch) +- + ((dst_rect->left / dst_format->block_width) * dst_format->block_byte_count); ++ dbuf = (BYTE *)dst_data ++ + ((dst_rect->top / dst_format->block_height) * dst_row_pitch) ++ + ((dst_rect->left / dst_format->block_width) * dst_format->block_byte_count); + + if (src_format->flags & dst_format->flags & WINED3DFMT_FLAG_BLOCKS) + { +@@ -4454,7 +4475,7 @@ static HRESULT surface_cpu_blt(struct wined3d_surface *dst_surface, const RECT * + } + + hr = surface_cpu_blt_compressed(sbase, dbuf, +- src_map.row_pitch, dst_map.row_pitch, dstwidth, dstheight, ++ src_row_pitch, dst_row_pitch, dstwidth, dstheight, + src_format, flags, fx); + goto release; + } +@@ -4462,7 +4483,7 @@ static HRESULT surface_cpu_blt(struct wined3d_surface *dst_surface, const RECT * + /* First, all the 'source-less' blits */ + if (flags & WINEDDBLT_COLORFILL) + { +- hr = _Blt_ColorFill(dbuf, dstwidth, dstheight, bpp, dst_map.row_pitch, fx->u5.dwFillColor); ++ hr = _Blt_ColorFill(dbuf, dstwidth, dstheight, bpp, dst_row_pitch, fx->u5.dwFillColor); + flags &= ~WINEDDBLT_COLORFILL; + } + +@@ -4476,12 +4497,12 @@ static HRESULT surface_cpu_blt(struct wined3d_surface *dst_surface, const RECT * + switch (fx->dwROP) + { + case BLACKNESS: +- hr = _Blt_ColorFill(dbuf, dstwidth, dstheight, bpp, dst_map.row_pitch, 0); ++ hr = _Blt_ColorFill(dbuf, dstwidth, dstheight, bpp, dst_row_pitch, 0); + break; + case 0xaa0029: /* No-op */ + break; + case WHITENESS: +- hr = _Blt_ColorFill(dbuf, dstwidth, dstheight, bpp, dst_map.row_pitch, ~0U); ++ hr = _Blt_ColorFill(dbuf, dstwidth, dstheight, bpp, dst_row_pitch, ~0U); + break; + case SRCCOPY: /* Well, we do that below? */ + break; +@@ -4532,19 +4553,19 @@ static HRESULT surface_cpu_blt(struct wined3d_surface *dst_surface, const RECT * + for (y = 0; y < dstheight; ++y) + { + memcpy(dbuf, sbuf, width); +- sbuf += src_map.row_pitch; +- dbuf += dst_map.row_pitch; ++ sbuf += src_row_pitch; ++ dbuf += dst_row_pitch; + } + } + else if (dst_rect->top > src_rect->top) + { + /* Copy from bottom upwards. */ +- sbuf += src_map.row_pitch * dstheight; +- dbuf += dst_map.row_pitch * dstheight; ++ sbuf += src_row_pitch * dstheight; ++ dbuf += dst_row_pitch * dstheight; + for (y = 0; y < dstheight; ++y) + { +- sbuf -= src_map.row_pitch; +- dbuf -= dst_map.row_pitch; ++ sbuf -= src_row_pitch; ++ dbuf -= dst_row_pitch; + memcpy(dbuf, sbuf, width); + } + } +@@ -4554,8 +4575,8 @@ static HRESULT surface_cpu_blt(struct wined3d_surface *dst_surface, const RECT * + for (y = 0; y < dstheight; ++y) + { + memmove(dbuf, sbuf, width); +- sbuf += src_map.row_pitch; +- dbuf += dst_map.row_pitch; ++ sbuf += src_row_pitch; ++ dbuf += dst_row_pitch; + } + } + } +@@ -4564,9 +4585,9 @@ static HRESULT surface_cpu_blt(struct wined3d_surface *dst_surface, const RECT * + /* Stretching in y direction only. */ + for (y = sy = 0; y < dstheight; ++y, sy += yinc) + { +- sbuf = sbase + (sy >> 16) * src_map.row_pitch; ++ sbuf = sbase + (sy >> 16) * src_row_pitch; + memcpy(dbuf, sbuf, width); +- dbuf += dst_map.row_pitch; ++ dbuf += dst_row_pitch; + } + } + } +@@ -4576,13 +4597,13 @@ static HRESULT surface_cpu_blt(struct wined3d_surface *dst_surface, const RECT * + int last_sy = -1; + for (y = sy = 0; y < dstheight; ++y, sy += yinc) + { +- sbuf = sbase + (sy >> 16) * src_map.row_pitch; ++ sbuf = sbase + (sy >> 16) * src_row_pitch; + + if ((sy >> 16) == (last_sy >> 16)) + { + /* This source row is the same as last source row - + * Copy the already stretched row. */ +- memcpy(dbuf, dbuf - dst_map.row_pitch, width); ++ memcpy(dbuf, dbuf - dst_row_pitch, width); + } + else + { +@@ -4629,14 +4650,14 @@ do { \ + } + #undef STRETCH_ROW + } +- dbuf += dst_map.row_pitch; ++ dbuf += dst_row_pitch; + last_sy = sy; + } + } + } + else + { +- LONG dstyinc = dst_map.row_pitch, dstxinc = bpp; ++ LONG dstyinc = dst_row_pitch, dstxinc = bpp; + DWORD keylow = 0xffffffff, keyhigh = 0, keymask = 0xffffffff; + DWORD destkeylow = 0x0, destkeyhigh = 0xffffffff, destkeymask = 0xffffffff; + if (flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYDEST | WINEDDBLT_KEYSRCOVERRIDE | WINEDDBLT_KEYDESTOVERRIDE)) +@@ -4686,7 +4707,7 @@ do { \ + LONG tmpxy; + dTopLeft = dbuf; + dTopRight = dbuf + ((dstwidth - 1) * bpp); +- dBottomLeft = dTopLeft + ((dstheight - 1) * dst_map.row_pitch); ++ dBottomLeft = dTopLeft + ((dstheight - 1) * dst_row_pitch); + dBottomRight = dBottomLeft + ((dstwidth - 1) * bpp); + + if (fx->dwDDFX & WINEDDBLTFX_ARITHSTRETCHY) +@@ -4769,7 +4790,7 @@ do { \ + type *d = (type *)dbuf, *dx, tmp; \ + for (y = sy = 0; y < dstheight; ++y, sy += yinc) \ + { \ +- s = (const type *)(sbase + (sy >> 16) * src_map.row_pitch); \ ++ s = (const type *)(sbase + (sy >> 16) * src_row_pitch); \ + dx = d; \ + for (x = sx = 0; x < dstwidth; ++x, sx += xinc) \ + { \ +@@ -4802,7 +4823,7 @@ do { \ + BYTE *d = dbuf, *dx; + for (y = sy = 0; y < dstheight; ++y, sy += yinc) + { +- sbuf = sbase + (sy >> 16) * src_map.row_pitch; ++ sbuf = sbase + (sy >> 16) * src_row_pitch; + dx = d; + for (x = sx = 0; x < dstwidth; ++x, sx+= xinc) + { +@@ -4833,6 +4854,10 @@ do { \ + } + } + ++ wined3d_resource_invalidate_location(&dst_surface->resource, ~dst_surface->resource.map_binding); ++ if (dst_surface->container) ++ wined3d_texture_set_dirty(dst_surface->container); ++ + error: + if (flags && FIXME_ON(d3d_surface)) + { +@@ -4840,12 +4865,24 @@ error: + } + + release: +- wined3d_surface_unmap(dst_surface); +- if (src_surface && src_surface != dst_surface) +- wined3d_surface_unmap(src_surface); ++ if (dst_data) ++ { ++ wined3d_resource_release_map_ptr(&dst_surface->resource, context); ++ ++ if (dst_surface->container->swapchain ++ && dst_surface->container == dst_surface->container->swapchain->front_buffer) ++ { ++ dst_surface->lockedRect = *dst_rect; ++ dst_surface->surface_ops->surface_frontbuffer_updated(dst_surface); ++ } ++ } ++ if (src_surface && src_surface != dst_surface && src_data) ++ wined3d_resource_release_map_ptr(&src_surface->resource, context); + /* Release the converted surface, if any. */ + if (src_texture) + wined3d_texture_decref(src_texture); ++ if (context) ++ context_release(context); + + return hr; + } +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0043-wined3d-Move-the-framebuffer-into-wined3d_state.patch b/patches/wined3d-CSMT_Main/0043-wined3d-Move-the-framebuffer-into-wined3d_state.patch new file mode 100644 index 00000000..453220cb --- /dev/null +++ b/patches/wined3d-CSMT_Main/0043-wined3d-Move-the-framebuffer-into-wined3d_state.patch @@ -0,0 +1,932 @@ +From b9c81476bc8d3bc8aa55fac10f0c7fc22a74dcb0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 20 Dec 2012 13:09:17 +0100 +Subject: wined3d: Move the framebuffer into wined3d_state + +--- + dlls/wined3d/arb_program_shader.c | 4 +- + dlls/wined3d/context.c | 20 +++++-- + dlls/wined3d/cs.c | 21 ++----- + dlls/wined3d/device.c | 117 +++++++++++++++++--------------------- + dlls/wined3d/drawprim.c | 14 ++--- + dlls/wined3d/glsl_shader.c | 2 +- + dlls/wined3d/shader.c | 2 +- + dlls/wined3d/state.c | 18 +++--- + dlls/wined3d/stateblock.c | 45 +++++++++++++-- + dlls/wined3d/surface.c | 2 +- + dlls/wined3d/swapchain.c | 2 +- + dlls/wined3d/utils.c | 2 +- + dlls/wined3d/wined3d_private.h | 46 +++++++++++---- + 13 files changed, 170 insertions(+), 125 deletions(-) + +diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c +index f612099..2875fe1 100644 +--- a/dlls/wined3d/arb_program_shader.c ++++ b/dlls/wined3d/arb_program_shader.c +@@ -706,7 +706,7 @@ static void shader_arb_load_constants_internal(struct shader_arb_priv *priv, + { + const struct wined3d_shader *pshader = state->shader[WINED3D_SHADER_TYPE_PIXEL]; + const struct arb_ps_compiled_shader *gl_shader = priv->compiled_fprog; +- UINT rt_height = state->fb->render_targets[0]->height; ++ UINT rt_height = state->fb.render_targets[0]->height; + + /* Load DirectX 9 float constants for pixel shader */ + priv->highest_dirty_ps_const = shader_arb_load_constantsF(pshader, gl_info, GL_FRAGMENT_PROGRAM_ARB, +@@ -4674,7 +4674,7 @@ static void shader_arb_select(void *shader_priv, struct wined3d_context *context + } + else + { +- UINT rt_height = state->fb->render_targets[0]->height; ++ UINT rt_height = state->fb.render_targets[0]->height; + shader_arb_ps_local_constants(compiled, context, state, rt_height); + } + +diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c +index cc60348..679e728 100644 +--- a/dlls/wined3d/context.c ++++ b/dlls/wined3d/context.c +@@ -1448,6 +1448,12 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain, + goto out; + } + ++ ret->current_fb.render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ++ sizeof(*ret->current_fb.render_targets) * gl_info->limits.buffers); ++ ret->current_fb.rt_size = gl_info->limits.buffers; ++ if (!ret->current_fb.render_targets) ++ goto out; ++ + /* Initialize the texture unit mapping to a 1:1 mapping */ + for (s = 0; s < MAX_COMBINED_SAMPLERS; ++s) + { +@@ -1764,6 +1770,7 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain, + + out: + device->shader_backend->shader_free_context_data(ret); ++ HeapFree(GetProcessHeap(), 0, ret->current_fb.render_targets); + HeapFree(GetProcessHeap(), 0, ret->free_event_queries); + HeapFree(GetProcessHeap(), 0, ret->free_occlusion_queries); + HeapFree(GetProcessHeap(), 0, ret->free_timestamp_queries); +@@ -1797,6 +1804,7 @@ void context_destroy(struct wined3d_device *device, struct wined3d_context *cont + } + + device->shader_backend->shader_free_context_data(context); ++ HeapFree(GetProcessHeap(), 0, context->current_fb.render_targets); + HeapFree(GetProcessHeap(), 0, context->draw_buffers); + HeapFree(GetProcessHeap(), 0, context->blit_targets); + device_context_remove(device, context); +@@ -2306,7 +2314,7 @@ BOOL context_apply_clear_state(struct wined3d_context *context, const struct win + DWORD rt_mask = 0, *cur_mask; + UINT i; + +- if (isStateDirty(context, STATE_FRAMEBUFFER) || fb != &device->fb ++ if (isStateDirty(context, STATE_FRAMEBUFFER) || !wined3d_fb_equal(fb, &context->current_fb) + || rt_count != context->gl_info->limits.buffers) + { + if (!context_validate_rt_config(rt_count, rts, fb->depth_stencil)) +@@ -2349,6 +2357,8 @@ BOOL context_apply_clear_state(struct wined3d_context *context, const struct win + rt_mask = context_generate_rt_mask_no_fbo(device, + rt_count ? wined3d_rendertarget_view_get_surface(rts[0]) : NULL); + } ++ ++ wined3d_fb_copy(&context->current_fb, fb); + } + else if (wined3d_settings.offscreen_rendering_mode == ORM_FBO + && (!rt_count || wined3d_resource_is_offscreen(rts[0]->resource))) +@@ -2399,7 +2409,7 @@ BOOL context_apply_clear_state(struct wined3d_context *context, const struct win + static DWORD find_draw_buffers_mask(const struct wined3d_context *context, const struct wined3d_device *device) + { + const struct wined3d_state *state = &device->state; +- struct wined3d_rendertarget_view **rts = state->fb->render_targets; ++ struct wined3d_rendertarget_view **rts = state->fb.render_targets; + struct wined3d_shader *ps = state->shader[WINED3D_SHADER_TYPE_PIXEL]; + DWORD rt_mask, rt_mask_bits; + unsigned int i; +@@ -2429,7 +2439,7 @@ static DWORD find_draw_buffers_mask(const struct wined3d_context *context, const + void context_state_fb(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) + { + const struct wined3d_device *device = context->swapchain->device; +- const struct wined3d_fb_state *fb = state->fb; ++ const struct wined3d_fb_state *fb = &state->fb; + DWORD rt_mask = find_draw_buffers_mask(context, device); + DWORD *cur_mask; + +@@ -2459,6 +2469,8 @@ void context_state_fb(struct wined3d_context *context, const struct wined3d_stat + context_apply_draw_buffers(context, rt_mask); + *cur_mask = rt_mask; + } ++ ++ wined3d_fb_copy(&context->current_fb, &state->fb); + } + + static void context_map_stage(struct wined3d_context *context, DWORD stage, DWORD unit) +@@ -2960,7 +2972,7 @@ BOOL context_apply_draw_state(struct wined3d_context *context, struct wined3d_de + { + const struct wined3d_state *state = &device->state; + const struct StateEntry *state_table = context->state_table; +- const struct wined3d_fb_state *fb = state->fb; ++ const struct wined3d_fb_state *fb = &state->fb; + unsigned int i, j; + WORD map; + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index b8a32e5..7bebe80 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -280,7 +280,7 @@ static void wined3d_cs_exec_clear(struct wined3d_cs *cs, const void *data) + 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, ++ &cs->state.fb, op->rect_count, op->rects, &draw_rect, op->flags, + op->color, op->depth, op->stencil); + } + +@@ -387,7 +387,7 @@ static void wined3d_cs_exec_set_rendertarget_view(struct wined3d_cs *cs, const v + { + const struct wined3d_cs_set_rendertarget_view *op = data; + +- cs->state.fb->render_targets[op->view_idx] = op->view; ++ cs->state.fb.render_targets[op->view_idx] = op->view; + device_invalidate_state(cs->device, STATE_FRAMEBUFFER); + } + +@@ -410,7 +410,7 @@ static void wined3d_cs_exec_set_depth_stencil_view(struct wined3d_cs *cs, const + struct wined3d_device *device = cs->device; + struct wined3d_rendertarget_view *prev; + +- if ((prev = cs->state.fb->depth_stencil)) ++ if ((prev = cs->state.fb.depth_stencil)) + { + struct wined3d_surface *prev_surface = wined3d_rendertarget_view_get_surface(prev); + +@@ -426,7 +426,7 @@ static void wined3d_cs_exec_set_depth_stencil_view(struct wined3d_cs *cs, const + } + } + +- cs->fb.depth_stencil = op->view; ++ cs->state.fb.depth_stencil = op->view; + + if (!prev != !op->view) + { +@@ -893,7 +893,7 @@ static void wined3d_cs_exec_reset_state(struct wined3d_cs *cs, const void *data) + + 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, ++ if (FAILED(hr = state_init(&cs->state, &adapter->gl_info, &adapter->d3d_info, + WINED3D_STATE_NO_REF | WINED3D_STATE_INIT_DEFAULT))) + ERR("Failed to initialize CS state, hr %#x.\n", hr); + } +@@ -975,17 +975,9 @@ struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device) + 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, ++ if (FAILED(state_init(&cs->state, 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; + } +@@ -1006,7 +998,6 @@ struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device) + void wined3d_cs_destroy(struct wined3d_cs *cs) + { + state_cleanup(&cs->state); +- HeapFree(GetProcessHeap(), 0, cs->fb.render_targets); + HeapFree(GetProcessHeap(), 0, cs->data); + HeapFree(GetProcessHeap(), 0, cs); + } +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index 565a92c..92478d7 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -851,7 +851,7 @@ static void device_init_swapchain_state(struct wined3d_device *device, struct wi + BOOL ds_enable = !!swapchain->desc.enable_auto_depth_stencil; + unsigned int i; + +- if (device->fb.render_targets) ++ if (device->state.fb.render_targets) + { + for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i) + { +@@ -869,7 +869,6 @@ HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device, + struct wined3d_swapchain_desc *swapchain_desc) + { + static const struct wined3d_color black = {0.0f, 0.0f, 0.0f, 0.0f}; +- const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; + struct wined3d_swapchain *swapchain = NULL; + struct wined3d_context *context; + DWORD clear_flags = 0; +@@ -882,9 +881,6 @@ HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device, + if (device->wined3d->flags & WINED3D_NO3D) + return WINED3DERR_INVALIDCALL; + +- device->fb.render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, +- sizeof(*device->fb.render_targets) * gl_info->limits.buffers); +- + if (FAILED(hr = device->shader_backend->shader_alloc_private(device, + device->adapter->vertex_pipe, device->adapter->fragment_pipe))) + { +@@ -972,7 +968,6 @@ HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device, + return WINED3D_OK; + + err_out: +- HeapFree(GetProcessHeap(), 0, device->fb.render_targets); + HeapFree(GetProcessHeap(), 0, device->swapchains); + device->swapchain_count = 0; + if (device->back_buffer_view) +@@ -1044,8 +1039,25 @@ HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device) + if (device->cursor_texture) + wined3d_texture_decref(device->cursor_texture); + ++ /* Release the buffers (with sanity checks). ++ * FIXME: Move this move into a separate patch. I think the idea ++ * behind this is that those surfaces should be freed before unloading ++ * remaining resources below. */ ++ if (device->onscreen_depth_stencil) ++ { ++ surface = device->onscreen_depth_stencil; ++ device->onscreen_depth_stencil = NULL; ++ wined3d_surface_decref(surface); ++ } ++ + state_unbind_resources(&device->state); + ++ if (device->auto_depth_stencil_view) ++ { ++ wined3d_rendertarget_view_decref(device->auto_depth_stencil_view); ++ device->auto_depth_stencil_view = NULL; ++ } ++ + /* Unload resources */ + LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &device->resources, struct wined3d_resource, resource_list_entry) + { +@@ -1068,37 +1080,6 @@ HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device) + device->shader_backend->shader_free_private(device); + destroy_dummy_textures(device, gl_info); + +- /* Release the buffers (with sanity checks)*/ +- if (device->onscreen_depth_stencil) +- { +- surface = device->onscreen_depth_stencil; +- device->onscreen_depth_stencil = NULL; +- wined3d_surface_decref(surface); +- } +- +- if (device->fb.depth_stencil) +- { +- struct wined3d_rendertarget_view *view = device->fb.depth_stencil; +- +- TRACE("Releasing depth/stencil view %p.\n", view); +- +- device->fb.depth_stencil = NULL; +- wined3d_rendertarget_view_decref(view); +- } +- +- if (device->auto_depth_stencil_view) +- { +- struct wined3d_rendertarget_view *view = device->auto_depth_stencil_view; +- +- device->auto_depth_stencil_view = NULL; +- if (wined3d_rendertarget_view_decref(view)) +- ERR("Something's still holding the auto depth/stencil view (%p).\n", view); +- } +- +- for (i = 0; i < gl_info->limits.buffers; ++i) +- { +- wined3d_device_set_rendertarget_view(device, i, NULL, FALSE); +- } + if (device->back_buffer_view) + { + wined3d_rendertarget_view_decref(device->back_buffer_view); +@@ -1118,9 +1099,6 @@ HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device) + device->swapchains = NULL; + device->swapchain_count = 0; + +- HeapFree(GetProcessHeap(), 0, device->fb.render_targets); +- device->fb.render_targets = NULL; +- + device->d3d_initialized = FALSE; + + return WINED3D_OK; +@@ -1910,7 +1888,7 @@ static void resolve_depth_buffer(struct wined3d_state *state) + || !(texture->resource.format->flags & WINED3DFMT_FLAG_DEPTH)) + return; + surface = surface_from_resource(texture->sub_resources[0]); +- if (!(depth_stencil = wined3d_rendertarget_view_get_surface(state->fb->depth_stencil))) ++ if (!(depth_stencil = wined3d_rendertarget_view_get_surface(state->fb.depth_stencil))) + return; + + wined3d_surface_blt(surface, NULL, depth_stencil, NULL, 0, NULL, WINED3D_TEXF_POINT); +@@ -3299,6 +3277,8 @@ HRESULT CDECL wined3d_device_present(const struct wined3d_device *device, const + HRESULT CDECL wined3d_device_clear(struct wined3d_device *device, DWORD rect_count, + const RECT *rects, DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil) + { ++ const struct wined3d_fb_state *fb = &device->state.fb; ++ + TRACE("device %p, rect_count %u, rects %p, flags %#x, color {%.8e, %.8e, %.8e, %.8e}, depth %.8e, stencil %u.\n", + device, rect_count, rects, flags, color->r, color->g, color->b, color->a, depth, stencil); + +@@ -3310,7 +3290,7 @@ HRESULT CDECL wined3d_device_clear(struct wined3d_device *device, DWORD rect_cou + + if (flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL)) + { +- struct wined3d_rendertarget_view *ds = device->fb.depth_stencil; ++ struct wined3d_rendertarget_view *ds = fb->depth_stencil; + if (!ds) + { + WARN("Clearing depth and/or stencil without a depth stencil buffer attached, returning WINED3DERR_INVALIDCALL\n"); +@@ -3319,8 +3299,8 @@ HRESULT CDECL wined3d_device_clear(struct wined3d_device *device, DWORD rect_cou + } + else if (flags & WINED3DCLEAR_TARGET) + { +- if (ds->width < device->fb.render_targets[0]->width +- || ds->height < device->fb.render_targets[0]->height) ++ if (ds->width < fb->render_targets[0]->width ++ || ds->height < fb->render_targets[0]->height) + { + WARN("Silently ignoring depth and target clear with mismatching sizes\n"); + return WINED3D_OK; +@@ -3668,8 +3648,8 @@ HRESULT CDECL wined3d_device_validate_device(const struct wined3d_device *device + if (state->render_states[WINED3D_RS_ZENABLE] || state->render_states[WINED3D_RS_ZWRITEENABLE] + || state->render_states[WINED3D_RS_STENCILENABLE]) + { +- struct wined3d_rendertarget_view *rt = device->fb.render_targets[0]; +- struct wined3d_rendertarget_view *ds = device->fb.depth_stencil; ++ struct wined3d_rendertarget_view *rt = state->fb.render_targets[0]; ++ struct wined3d_rendertarget_view *ds = state->fb.depth_stencil; + + if (ds && rt && (ds->width < rt->width || ds->height < rt->height)) + { +@@ -3895,20 +3875,21 @@ struct wined3d_rendertarget_view * CDECL wined3d_device_get_rendertarget_view(co + return NULL; + } + +- return device->fb.render_targets[view_idx]; ++ return device->state.fb.render_targets[view_idx]; + } + + struct wined3d_rendertarget_view * CDECL wined3d_device_get_depth_stencil_view(const struct wined3d_device *device) + { + TRACE("device %p.\n", device); + +- return device->fb.depth_stencil; ++ return device->state.fb.depth_stencil; + } + + HRESULT CDECL wined3d_device_set_rendertarget_view(struct wined3d_device *device, + unsigned int view_idx, struct wined3d_rendertarget_view *view, BOOL set_viewport) + { + struct wined3d_rendertarget_view *prev; ++ struct wined3d_fb_state *fb = &device->state.fb; + + TRACE("device %p, view_idx %u, view %p, set_viewport %#x.\n", + device, view_idx, view, set_viewport); +@@ -3948,13 +3929,13 @@ HRESULT CDECL wined3d_device_set_rendertarget_view(struct wined3d_device *device + } + + +- prev = device->fb.render_targets[view_idx]; ++ prev = fb->render_targets[view_idx]; + if (view == prev) + return WINED3D_OK; + + if (view) + wined3d_rendertarget_view_incref(view); +- device->fb.render_targets[view_idx] = view; ++ fb->render_targets[view_idx] = view; + wined3d_cs_emit_set_rendertarget_view(device->cs, view_idx, view); + /* Release after the assignment, to prevent device_resource_released() + * from seeing the surface as still in use. */ +@@ -3966,18 +3947,19 @@ HRESULT CDECL wined3d_device_set_rendertarget_view(struct wined3d_device *device + + void CDECL wined3d_device_set_depth_stencil_view(struct wined3d_device *device, struct wined3d_rendertarget_view *view) + { ++ struct wined3d_fb_state *fb = &device->state.fb; + struct wined3d_rendertarget_view *prev; + + TRACE("device %p, view %p.\n", device, view); + +- prev = device->fb.depth_stencil; ++ prev = fb->depth_stencil; + if (prev == view) + { + TRACE("Trying to do a NOP SetRenderTarget operation.\n"); + return; + } + +- if ((device->fb.depth_stencil = view)) ++ if ((fb->depth_stencil = view)) + wined3d_rendertarget_view_incref(view); + wined3d_cs_emit_set_depth_stencil_view(device->cs, view); + if (prev) +@@ -4350,10 +4332,9 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device, + wined3d_texture_decref(device->cursor_texture); + device->cursor_texture = NULL; + } +- state_unbind_resources(&device->state); + } + +- if (device->fb.render_targets) ++ if (device->state.fb.render_targets) + { + for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i) + { +@@ -4362,6 +4343,11 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device, + } + wined3d_device_set_depth_stencil_view(device, NULL); + ++ if (reset_state) ++ { ++ state_unbind_resources(&device->state); ++ } ++ + if (device->onscreen_depth_stencil) + { + wined3d_surface_decref(device->onscreen_depth_stencil); +@@ -4644,7 +4630,7 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device, + if (device->d3d_initialized) + delete_opengl_contexts(device, swapchain); + +- if (FAILED(hr = state_init(&device->state, &device->fb, &device->adapter->gl_info, ++ if (FAILED(hr = state_init(&device->state, &device->adapter->gl_info, + &device->adapter->d3d_info, WINED3D_STATE_INIT_DEFAULT))) + ERR("Failed to initialize device state, hr %#x.\n", hr); + device->update_state = &device->state; +@@ -4653,22 +4639,21 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device, + } + else if (device->back_buffer_view) + { +- struct wined3d_rendertarget_view *view = device->back_buffer_view; + struct wined3d_state *state = &device->state; + +- wined3d_device_set_rendertarget_view(device, 0, view, FALSE); ++ wined3d_device_set_rendertarget_view(device, 0, device->back_buffer_view, FALSE); + + /* Note the min_z / max_z is not reset. */ + state->viewport.x = 0; + state->viewport.y = 0; +- state->viewport.width = view->width; +- state->viewport.height = view->height; ++ state->viewport.width = swapchain->desc.backbuffer_width; ++ state->viewport.height = swapchain->desc.backbuffer_height; + wined3d_cs_emit_set_viewport(device->cs, &state->viewport); + + state->scissor_rect.top = 0; + state->scissor_rect.left = 0; +- state->scissor_rect.right = view->width; +- state->scissor_rect.bottom = view->height; ++ state->scissor_rect.right = swapchain->desc.backbuffer_width; ++ state->scissor_rect.bottom = swapchain->desc.backbuffer_height; + wined3d_cs_emit_set_scissor_rect(device->cs, &state->scissor_rect); + } + +@@ -4759,17 +4744,17 @@ void device_resource_released(struct wined3d_device *device, struct wined3d_reso + + for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i) + { +- if (wined3d_rendertarget_view_get_surface(device->fb.render_targets[i]) == surface) ++ if (wined3d_rendertarget_view_get_surface(device->state.fb.render_targets[i]) == surface) + { + ERR("Surface %p is still in use as render target %u.\n", surface, i); +- device->fb.render_targets[i] = NULL; ++ device->state.fb.render_targets[i] = NULL; + } + } + +- if (wined3d_rendertarget_view_get_surface(device->fb.depth_stencil) == surface) ++ if (wined3d_rendertarget_view_get_surface(device->state.fb.depth_stencil) == surface) + { + ERR("Surface %p is still in use as depth/stencil buffer.\n", surface); +- device->fb.depth_stencil = NULL; ++ device->state.fb.depth_stencil = NULL; + } + } + break; +@@ -4910,7 +4895,7 @@ HRESULT device_init(struct wined3d_device *device, struct wined3d *wined3d, + + device->blitter = adapter->blitter; + +- if (FAILED(hr = state_init(&device->state, &device->fb, &adapter->gl_info, ++ if (FAILED(hr = state_init(&device->state, &adapter->gl_info, + &adapter->d3d_info, WINED3D_STATE_INIT_DEFAULT))) + { + ERR("Failed to initialize device state, hr %#x.\n", hr); +diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c +index 62b7032..98261f9 100644 +--- a/dlls/wined3d/drawprim.c ++++ b/dlls/wined3d/drawprim.c +@@ -608,7 +608,7 @@ void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_co + + if (!index_count) return; + +- context = context_acquire(device, wined3d_rendertarget_view_get_surface(device->fb.render_targets[0])); ++ context = context_acquire(device, wined3d_rendertarget_view_get_surface(state->fb.render_targets[0])); + if (!context->valid) + { + context_release(context); +@@ -622,7 +622,7 @@ void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_co + /* Invalidate the back buffer memory so LockRect will read it the next time */ + for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i) + { +- struct wined3d_surface *target = wined3d_rendertarget_view_get_surface(device->fb.render_targets[i]); ++ struct wined3d_surface *target = wined3d_rendertarget_view_get_surface(state->fb.render_targets[i]); + if (target) + { + wined3d_resource_load_location(&target->resource, context, target->container->resource.draw_binding); +@@ -631,18 +631,18 @@ void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_co + } + } + +- if (device->fb.depth_stencil) ++ if (state->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 ++ DWORD location = context->render_offscreen ? state->fb.depth_stencil->resource->draw_binding + : WINED3D_LOCATION_DRAWABLE; + if (state->render_states[WINED3D_RS_ZWRITEENABLE] || state->render_states[WINED3D_RS_ZENABLE]) + { +- struct wined3d_surface *ds = wined3d_rendertarget_view_get_surface(device->fb.depth_stencil); ++ struct wined3d_surface *ds = wined3d_rendertarget_view_get_surface(state->fb.depth_stencil); + RECT current_rect, draw_rect, r; + + if (!context->render_offscreen && ds != device->onscreen_depth_stencil) +@@ -668,9 +668,9 @@ void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_co + return; + } + +- if (device->fb.depth_stencil && state->render_states[WINED3D_RS_ZWRITEENABLE]) ++ if (state->fb.depth_stencil && state->render_states[WINED3D_RS_ZWRITEENABLE]) + { +- struct wined3d_surface *ds = wined3d_rendertarget_view_get_surface(device->fb.depth_stencil); ++ struct wined3d_surface *ds = wined3d_rendertarget_view_get_surface(state->fb.depth_stencil); + 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); +diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c +index 0ab591f..4ef473b 100644 +--- a/dlls/wined3d/glsl_shader.c ++++ b/dlls/wined3d/glsl_shader.c +@@ -957,7 +957,7 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont + const struct wined3d_state *state = &shader->device->state; + const struct ps_compile_args *ps_args = ctx_priv->cur_ps_args; + const struct wined3d_gl_info *gl_info = context->gl_info; +- const struct wined3d_fb_state *fb = &shader->device->fb; ++ const struct wined3d_fb_state *fb = &state->fb; + unsigned int i, extra_constants_needed = 0; + const struct wined3d_shader_lconst *lconst; + const char *prefix; +diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c +index 6531803..cc969b8 100644 +--- a/dlls/wined3d/shader.c ++++ b/dlls/wined3d/shader.c +@@ -2184,7 +2184,7 @@ void find_ps_compile_args(const struct wined3d_state *state, const struct wined3 + 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]) + { +- const struct wined3d_format *rt_format = state->fb->render_targets[0]->format; ++ const struct wined3d_format *rt_format = state->fb.render_targets[0]->format; + if (rt_format->flags & WINED3DFMT_FLAG_SRGB_WRITE) + { + static unsigned int warned = 0; +diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c +index 700db84..20f00d6 100644 +--- a/dlls/wined3d/state.c ++++ b/dlls/wined3d/state.c +@@ -106,7 +106,7 @@ static void state_zenable(struct wined3d_context *context, const struct wined3d_ + static UINT once; + + /* No z test without depth stencil buffers */ +- if (!state->fb->depth_stencil) ++ if (!state->fb.depth_stencil) + { + TRACE("No Z buffer - disabling depth test\n"); + zenable = WINED3D_ZB_FALSE; +@@ -381,7 +381,7 @@ static GLenum gl_blend_factor(enum wined3d_blend factor, const struct wined3d_fo + + static void state_blend(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) + { +- const struct wined3d_format *rt_format = state->fb->render_targets[0]->format; ++ const struct wined3d_format *rt_format = state->fb.render_targets[0]->format; + const struct wined3d_gl_info *gl_info = context->gl_info; + GLenum srcBlend, dstBlend; + enum wined3d_blend d3d_blend; +@@ -826,7 +826,7 @@ static void state_stencil(struct wined3d_context *context, const struct wined3d_ + GLint depthFail_ccw; + + /* No stencil test without a stencil buffer. */ +- if (!state->fb->depth_stencil) ++ if (!state->fb.depth_stencil) + { + gl_info->gl_ops.gl.p_glDisable(GL_STENCIL_TEST); + checkGLcall("glDisable GL_STENCIL_TEST"); +@@ -912,7 +912,7 @@ static void state_stencil(struct wined3d_context *context, const struct wined3d_ + + static void state_stencilwrite2s(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) + { +- DWORD mask = state->fb->depth_stencil ? state->render_states[WINED3D_RS_STENCILWRITEMASK] : 0; ++ DWORD mask = state->fb.depth_stencil ? state->render_states[WINED3D_RS_STENCILWRITEMASK] : 0; + const struct wined3d_gl_info *gl_info = context->gl_info; + + GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK)); +@@ -926,7 +926,7 @@ static void state_stencilwrite2s(struct wined3d_context *context, const struct w + + static void state_stencilwrite(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) + { +- DWORD mask = state->fb->depth_stencil ? state->render_states[WINED3D_RS_STENCILWRITEMASK] : 0; ++ DWORD mask = state->fb.depth_stencil ? state->render_states[WINED3D_RS_STENCILWRITEMASK] : 0; + const struct wined3d_gl_info *gl_info = context->gl_info; + + gl_info->gl_ops.gl.p_glStencilMask(mask); +@@ -1765,7 +1765,7 @@ static void state_depthbias(struct wined3d_context *context, const struct wined3 + if (state->render_states[WINED3D_RS_SLOPESCALEDEPTHBIAS] + || state->render_states[WINED3D_RS_DEPTHBIAS]) + { +- const struct wined3d_rendertarget_view *depth = state->fb->depth_stencil; ++ const struct wined3d_rendertarget_view *depth = state->fb.depth_stencil; + float scale; + + union +@@ -4653,7 +4653,7 @@ void vertexdeclaration(struct wined3d_context *context, const struct wined3d_sta + + static void viewport_miscpart(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) + { +- const struct wined3d_rendertarget_view *target = state->fb->render_targets[0]; ++ const struct wined3d_rendertarget_view *target = state->fb.render_targets[0]; + const struct wined3d_gl_info *gl_info = context->gl_info; + struct wined3d_viewport vp = state->viewport; + +@@ -4833,7 +4833,7 @@ static void scissorrect(struct wined3d_context *context, const struct wined3d_st + } + else + { +- const struct wined3d_rendertarget_view *target = state->fb->render_targets[0]; ++ const struct wined3d_rendertarget_view *target = state->fb.render_targets[0]; + UINT height; + UINT width; + +@@ -4900,7 +4900,7 @@ static void psorigin(struct wined3d_context *context, const struct wined3d_state + + void state_srgbwrite(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) + { +- const struct wined3d_format *rt_format = state->fb->render_targets[0]->format; ++ const struct wined3d_format *rt_format = state->fb.render_targets[0]->format; + 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/wined3d/stateblock.c b/dlls/wined3d/stateblock.c +index dc146fc..141e539 100644 +--- a/dlls/wined3d/stateblock.c ++++ b/dlls/wined3d/stateblock.c +@@ -464,6 +464,7 @@ void state_unbind_resources(struct wined3d_state *state) + struct wined3d_texture *texture; + struct wined3d_buffer *buffer; + struct wined3d_shader *shader; ++ struct wined3d_rendertarget_view *view; + unsigned int i, j; + + if ((decl = state->vertex_declaration)) +@@ -540,6 +541,31 @@ void state_unbind_resources(struct wined3d_state *state) + } + } + } ++ ++ if (state->fb.depth_stencil) ++ { ++ view = state->fb.depth_stencil; ++ ++ TRACE("Releasing depth/stencil buffer %p.\n", view); ++ ++ state->fb.depth_stencil = NULL; ++ wined3d_rendertarget_view_decref(view); ++ } ++ ++ if (state->fb.render_targets) ++ { ++ for (i = 0; i < state->fb.rt_size; i++) ++ { ++ view = state->fb.render_targets[i]; ++ TRACE("Setting rendertarget %u to NULL\n", i); ++ state->fb.render_targets[i] = NULL; ++ if (view) ++ { ++ TRACE("Releasing the rendertarget view at %p\n", view); ++ wined3d_rendertarget_view_decref(view); ++ } ++ } ++ } + } + + void state_cleanup(struct wined3d_state *state) +@@ -567,6 +593,7 @@ void state_cleanup(struct wined3d_state *state) + + HeapFree(GetProcessHeap(), 0, state->vs_consts_f); + HeapFree(GetProcessHeap(), 0, state->ps_consts_f); ++ HeapFree(GetProcessHeap(), 0, state->fb.render_targets); + } + + ULONG CDECL wined3d_stateblock_decref(struct wined3d_stateblock *stateblock) +@@ -1315,14 +1342,12 @@ static void state_init_default(struct wined3d_state *state, const struct wined3d + } + } + +-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) ++HRESULT state_init(struct wined3d_state *state, 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; + + for (i = 0; i < LIGHTMAP_SIZE; i++) + { +@@ -1340,6 +1365,15 @@ HRESULT state_init(struct wined3d_state *state, struct wined3d_fb_state *fb, + return E_OUTOFMEMORY; + } + ++ if (!(state->fb.render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ++ sizeof(*state->fb.render_targets) * gl_info->limits.buffers))) ++ { ++ HeapFree(GetProcessHeap(), 0, state->ps_consts_f); ++ HeapFree(GetProcessHeap(), 0, state->vs_consts_f); ++ return E_OUTOFMEMORY; ++ } ++ state->fb.rt_size = gl_info->limits.buffers; ++ + if (flags & WINED3D_STATE_INIT_DEFAULT) + state_init_default(state, gl_info); + +@@ -1350,12 +1384,13 @@ static HRESULT stateblock_init(struct wined3d_stateblock *stateblock, + struct wined3d_device *device, enum wined3d_stateblock_type type) + { + HRESULT hr; ++ const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; + 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))) ++ if (FAILED(hr = state_init(&stateblock->state, gl_info, d3d_info, 0))) + return hr; + + if (FAILED(hr = stateblock_allocate_shader_constants(stateblock))) +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 3702866..642210d 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -3332,9 +3332,9 @@ static HRESULT surface_blt_special(struct wined3d_surface *dst_surface, const RE + enum wined3d_texture_filter_type filter) + { + struct wined3d_device *device = dst_surface->resource.device; +- const struct wined3d_surface *rt = wined3d_rendertarget_view_get_surface(device->fb.render_targets[0]); + const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; + struct wined3d_swapchain *src_swapchain, *dst_swapchain; ++ const struct wined3d_surface *rt = wined3d_rendertarget_view_get_surface(device->state.fb.render_targets[0]); + + TRACE("dst_surface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, blt_fx %p, filter %s.\n", + dst_surface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), +diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c +index dd7d2c7..ed2964e 100644 +--- a/dlls/wined3d/swapchain.c ++++ b/dlls/wined3d/swapchain.c +@@ -421,7 +421,7 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT + { + 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; ++ const struct wined3d_fb_state *fb = &swapchain->device->state.fb; + const struct wined3d_gl_info *gl_info; + struct wined3d_context *context; + struct wined3d_surface *front; +diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c +index 6ce07b8..8ff4e3e 100644 +--- a/dlls/wined3d/utils.c ++++ b/dlls/wined3d/utils.c +@@ -3428,7 +3428,7 @@ void gen_ffp_frag_op(const struct wined3d_context *context, const struct wined3d + unsigned int i; + DWORD ttff; + DWORD cop, aop, carg0, carg1, carg2, aarg0, aarg1, aarg2; +- const struct wined3d_format *rt_format = state->fb->render_targets[0]->format; ++ const struct wined3d_format *rt_format = state->fb.render_targets[0]->format; + 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_private.h b/dlls/wined3d/wined3d_private.h +index 43e1c21..7339ae5 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -1088,6 +1088,36 @@ struct wined3d_timestamp_query + 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; + ++struct wined3d_fb_state ++{ ++ struct wined3d_rendertarget_view **render_targets; ++ struct wined3d_rendertarget_view *depth_stencil; ++ UINT rt_size; ++}; ++ ++static inline BOOL wined3d_fb_equal(const struct wined3d_fb_state *fb1, const struct wined3d_fb_state *fb2) ++{ ++ UINT i; ++ ++ if (fb1->depth_stencil != fb2->depth_stencil) ++ return FALSE; ++ if (fb1->rt_size != fb2->rt_size) ++ return FALSE; ++ for (i = 0; i < fb1->rt_size; i++) ++ if (fb1->render_targets[i] != fb2->render_targets[i]) ++ return FALSE; ++ return TRUE; ++} ++ ++static inline void wined3d_fb_copy(struct wined3d_fb_state *dst, const struct wined3d_fb_state *src) ++{ ++ UINT i; ++ ++ dst->depth_stencil = src->depth_stencil; ++ for (i = 0; i < min(dst->rt_size, src->rt_size); i++) ++ dst->render_targets[i] = src->render_targets[i]; ++} ++ + struct wined3d_context + { + const struct wined3d_gl_info *gl_info; +@@ -1102,6 +1132,7 @@ struct wined3d_context + 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 */ ++ struct wined3d_fb_state current_fb; + + struct wined3d_swapchain *swapchain; + struct wined3d_surface *current_rt; +@@ -1201,12 +1232,6 @@ struct wined3d_context + GLuint dummy_arbfp_prog; + }; + +-struct wined3d_fb_state +-{ +- struct wined3d_rendertarget_view **render_targets; +- struct wined3d_rendertarget_view *depth_stencil; +-}; +- + typedef void (*APPLYSTATEFUNC)(struct wined3d_context *ctx, const struct wined3d_state *state, DWORD state_id); + + struct StateEntry +@@ -1881,7 +1906,7 @@ struct wined3d_stream_state + struct wined3d_state + { + DWORD flags; +- const struct wined3d_fb_state *fb; ++ struct wined3d_fb_state fb; + + struct wined3d_vertex_declaration *vertex_declaration; + struct wined3d_stream_output stream_output[MAX_STREAM_OUT]; +@@ -1986,7 +2011,6 @@ struct wined3d_device + struct list shaders; /* a linked list to track shaders (pixel and vertex) */ + + /* Render Target Support */ +- struct wined3d_fb_state fb; + struct wined3d_surface *onscreen_depth_stencil; + struct wined3d_rendertarget_view *auto_depth_stencil_view; + +@@ -2497,9 +2521,8 @@ struct wined3d_stateblock + void stateblock_init_contained_states(struct wined3d_stateblock *stateblock) DECLSPEC_HIDDEN; + + void state_cleanup(struct wined3d_state *state) DECLSPEC_HIDDEN; +-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; ++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; + + struct wined3d_cs_ops +@@ -2512,7 +2535,6 @@ 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; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0044-wined3d-Get-rid-of-state-access-in-shader_generate_g.patch b/patches/wined3d-CSMT_Main/0044-wined3d-Get-rid-of-state-access-in-shader_generate_g.patch new file mode 100644 index 00000000..21ef5b99 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0044-wined3d-Get-rid-of-state-access-in-shader_generate_g.patch @@ -0,0 +1,63 @@ +From 25c76a39621543e2650531aef15d131d04927f3b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 20 Dec 2012 14:19:52 +0100 +Subject: wined3d: Get rid of state access in shader_generate_glsl_declarations + +--- + dlls/wined3d/glsl_shader.c | 21 ++++++--------------- + 1 file changed, 6 insertions(+), 15 deletions(-) + +diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c +index 4ef473b..3b049e6 100644 +--- a/dlls/wined3d/glsl_shader.c ++++ b/dlls/wined3d/glsl_shader.c +@@ -954,10 +954,8 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont + const struct wined3d_shader_reg_maps *reg_maps, const struct shader_glsl_ctx_priv *ctx_priv) + { + const struct wined3d_shader_version *version = ®_maps->shader_version; +- const struct wined3d_state *state = &shader->device->state; + const struct ps_compile_args *ps_args = ctx_priv->cur_ps_args; + const struct wined3d_gl_info *gl_info = context->gl_info; +- const struct wined3d_fb_state *fb = &state->fb; + unsigned int i, extra_constants_needed = 0; + const struct wined3d_shader_lconst *lconst; + const char *prefix; +@@ -1186,7 +1184,7 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont + { + UINT in_count = min(vec4_varyings(version->major, gl_info), shader->limits->packed_input); + +- if (use_vs(state)) ++ if (ps_args->vp_mode == vertexshader) + shader_addline(buffer, "varying vec4 %s_in[%u];\n", prefix, in_count); + else + /* TODO: Write a replacement shader for the fixed function +@@ -1233,21 +1231,14 @@ static void shader_generate_glsl_declarations(const struct wined3d_context *cont + } + else + { +- float ycorrection[] = +- { +- context->render_offscreen ? 0.0f : fb->render_targets[0]->height, +- context->render_offscreen ? 1.0f : -1.0f, +- 0.0f, +- 0.0f, +- }; +- + /* This happens because we do not have proper tracking of the + * constant registers that are actually used, only the max +- * limit of the shader version. */ ++ * limit of the shader version. ++ * ++ * FIXME 2: This is wrong, there's no need to do this. Get rid of ++ * it and just create the uniform. ++ */ + FIXME("Cannot find a free uniform for vpos correction params\n"); +- shader_addline(buffer, "const vec4 ycorrection = "); +- shader_glsl_append_imm_vec4(buffer, ycorrection); +- shader_addline(buffer, ";\n"); + } + shader_addline(buffer, "vec4 vpos;\n"); + } +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0045-wined3d-Preload-buffers-if-streamsrc-is-not-dirty.patch b/patches/wined3d-CSMT_Main/0045-wined3d-Preload-buffers-if-streamsrc-is-not-dirty.patch new file mode 100644 index 00000000..80e3b264 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0045-wined3d-Preload-buffers-if-streamsrc-is-not-dirty.patch @@ -0,0 +1,65 @@ +From b3e18543b31f43d2f72e4271c37f65c47e3f674f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Sun, 7 Jul 2013 12:06:31 +0200 +Subject: wined3d: Preload buffers if streamsrc is not dirty + +FIXME: Merge this with the preload calls done by +context_update_stream_info, preload only used buffers + +FIXME2: Merge this patch with the patch that removes +PreLoad from buffer_unmap + +FIXME3: There may be more unintended consequences of calling preload +here... +--- + dlls/wined3d/buffer.c | 2 +- + dlls/wined3d/context.c | 6 +++++- + dlls/wined3d/wined3d_private.h | 1 - + 3 files changed, 6 insertions(+), 3 deletions(-) + +diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c +index 2e44f0f..f335dfc 100644 +--- a/dlls/wined3d/buffer.c ++++ b/dlls/wined3d/buffer.c +@@ -711,7 +711,7 @@ static void buffer_direct_upload(struct wined3d_buffer *This, const struct wined + checkGLcall("glUnmapBufferARB"); + } + +-void buffer_mark_used(struct wined3d_buffer *buffer) ++static void buffer_mark_used(struct wined3d_buffer *buffer) + { + buffer->flags &= ~(WINED3D_BUFFER_SYNC | WINED3D_BUFFER_DISCARD); + } +diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c +index 679e728..ffb1c43 100644 +--- a/dlls/wined3d/context.c ++++ b/dlls/wined3d/context.c +@@ -2999,8 +2999,12 @@ BOOL context_apply_draw_state(struct wined3d_context *context, struct wined3d_de + for (i = 0, map = context->stream_info.use_map; map; map >>= 1, ++i) + { + if (map & 1) +- buffer_mark_used(state->streams[context->stream_info.elements[i].stream_idx].buffer); ++ buffer_internal_preload(state->streams[context->stream_info.elements[i].stream_idx].buffer, ++ context, state); + } ++ /* PreLoad may kick buffers out of vram. */ ++ if (isStateDirty(context, STATE_STREAMSRC)) ++ context_update_stream_info(context, state); + } + if (state->index_buffer) + { +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 7339ae5..9c05b6c 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2669,7 +2669,6 @@ void buffer_get_memory(struct wined3d_buffer *buffer, struct wined3d_context *co + 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; +-void buffer_mark_used(struct wined3d_buffer *buffer) DECLSPEC_HIDDEN; + + struct wined3d_rendertarget_view + { +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0046-wined3d-Hackily-introduce-a-multithreaded-command-st.patch b/patches/wined3d-CSMT_Main/0046-wined3d-Hackily-introduce-a-multithreaded-command-st.patch new file mode 100644 index 00000000..2b0ed80e --- /dev/null +++ b/patches/wined3d-CSMT_Main/0046-wined3d-Hackily-introduce-a-multithreaded-command-st.patch @@ -0,0 +1,867 @@ +From 5b81c252f4f8dbb4073e28b5a6d0c181b74facdc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Tue, 1 Oct 2013 14:31:56 +0200 +Subject: wined3d: Hackily introduce a multithreaded command stream + +--- + dlls/wined3d/cs.c | 376 ++++++++++++++++++++++++++++++++++++----- + dlls/wined3d/wined3d_main.c | 9 + + dlls/wined3d/wined3d_private.h | 18 ++ + 3 files changed, 365 insertions(+), 38 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 7bebe80..1122073 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -24,8 +24,19 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); + + #define WINED3D_INITIAL_CS_SIZE 4096 + ++static CRITICAL_SECTION wined3d_cs_list_mutex; ++static CRITICAL_SECTION_DEBUG wined3d_cs_list_mutex_debug = ++{ ++ 0, 0, &wined3d_cs_list_mutex, ++ {&wined3d_cs_list_mutex_debug.ProcessLocksList, ++ &wined3d_cs_list_mutex_debug.ProcessLocksList}, ++ 0, 0, {(DWORD_PTR)(__FILE__ ": wined3d_cs_list_mutex")} ++}; ++static CRITICAL_SECTION wined3d_cs_list_mutex = {&wined3d_cs_list_mutex_debug, -1, 0, 0, 0, 0}; ++ + enum wined3d_cs_op + { ++ WINED3D_CS_OP_FENCE, + WINED3D_CS_OP_PRESENT, + WINED3D_CS_OP_CLEAR, + WINED3D_CS_OP_DRAW, +@@ -51,6 +62,18 @@ enum wined3d_cs_op + WINED3D_CS_OP_SET_CLIP_PLANE, + WINED3D_CS_OP_SET_MATERIAL, + WINED3D_CS_OP_RESET_STATE, ++ WINED3D_CS_OP_STOP, ++}; ++ ++struct wined3d_cs_stop ++{ ++ enum wined3d_cs_op opcode; ++}; ++ ++struct wined3d_cs_fence ++{ ++ enum wined3d_cs_op opcode; ++ BOOL *signalled; + }; + + struct wined3d_cs_present +@@ -101,7 +124,7 @@ struct wined3d_cs_set_viewport + struct wined3d_cs_set_scissor_rect + { + enum wined3d_cs_op opcode; +- const RECT *rect; ++ RECT rect; + }; + + struct wined3d_cs_set_rendertarget_view +@@ -220,20 +243,20 @@ struct wined3d_cs_set_transform + { + enum wined3d_cs_op opcode; + enum wined3d_transform_state state; +- const struct wined3d_matrix *matrix; ++ 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_vec4 plane; + }; + + struct wined3d_cs_set_material + { + enum wined3d_cs_op opcode; +- const struct wined3d_material *material; ++ struct wined3d_material material; + }; + + struct wined3d_cs_reset_state +@@ -241,7 +264,134 @@ struct wined3d_cs_reset_state + enum wined3d_cs_op opcode; + }; + +-static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data) ++/* FIXME: The list synchronization probably isn't particularly fast. */ ++static void wined3d_cs_list_enqueue(struct wined3d_cs_list *list, struct wined3d_cs_block *block) ++{ ++ EnterCriticalSection(&wined3d_cs_list_mutex); ++ list_add_tail(&list->blocks, &block->entry); ++ LeaveCriticalSection(&wined3d_cs_list_mutex); ++} ++ ++static struct wined3d_cs_block *wined3d_cs_list_dequeue(struct wined3d_cs_list *list) ++{ ++ struct list *head; ++ ++ EnterCriticalSection(&wined3d_cs_list_mutex); ++ if (!(head = list_head(&list->blocks))) ++ { ++ LeaveCriticalSection(&wined3d_cs_list_mutex); ++ return NULL; ++ } ++ list_remove(head); ++ LeaveCriticalSection(&wined3d_cs_list_mutex); ++ ++ return LIST_ENTRY(head, struct wined3d_cs_block, entry); ++} ++ ++static struct wined3d_cs_block *wined3d_cs_list_dequeue_blocking(struct wined3d_cs_list *list) ++{ ++ struct wined3d_cs_block *block; ++ ++ /* FIXME: Use an event to wait after a couple of spins. */ ++ for (;;) ++ { ++ if ((block = wined3d_cs_list_dequeue(list))) ++ return block; ++ } ++} ++ ++static void wined3d_cs_list_init(struct wined3d_cs_list *list) ++{ ++ list_init(&list->blocks); ++} ++ ++static struct wined3d_cs_block *wined3d_cs_get_thread_block(const struct wined3d_cs *cs) ++{ ++ return TlsGetValue(cs->tls_idx); ++} ++ ++static void wined3d_cs_set_thread_block(const struct wined3d_cs *cs, struct wined3d_cs_block *block) ++{ ++ if (!TlsSetValue(cs->tls_idx, block)) ++ ERR("Failed to set thread block.\n"); ++} ++ ++static void wined3d_cs_flush(struct wined3d_cs *cs) ++{ ++ wined3d_cs_list_enqueue(&cs->exec_list, wined3d_cs_get_thread_block(cs)); ++ wined3d_cs_set_thread_block(cs, NULL); ++} ++ ++static struct wined3d_cs_block *wined3d_cs_get_block(struct wined3d_cs *cs) ++{ ++ struct wined3d_cs_block *block; ++ ++ if (!(block = wined3d_cs_list_dequeue(&cs->free_list))) ++ { ++ if (!(block = HeapAlloc(GetProcessHeap(), 0, sizeof(*block)))) ++ { ++ ERR("Failed to get new block.\n"); ++ return NULL; ++ } ++ } ++ ++ block->pos = 0; ++ ++ return block; ++} ++ ++static void *wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size) ++{ ++ struct wined3d_cs_block *block = wined3d_cs_get_thread_block(cs); ++ void *data; ++ ++ if (!block || block->pos + size > sizeof(block->data)) ++ { ++ if (block) ++ wined3d_cs_flush(cs); ++ block = wined3d_cs_get_block(cs); ++ wined3d_cs_set_thread_block(cs, block); ++ } ++ ++ data = &block->data[block->pos]; ++ block->pos += size; ++ ++ return data; ++} ++ ++static UINT wined3d_cs_exec_fence(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_fence *op = data; ++ ++ InterlockedExchange(op->signalled, TRUE); ++ ++ return sizeof(*op); ++} ++ ++static void wined3d_cs_emit_fence(struct wined3d_cs *cs, BOOL *signalled) ++{ ++ struct wined3d_cs_fence *op; ++ ++ *signalled = FALSE; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_FENCE; ++ op->signalled = signalled; ++} ++ ++static void wined3d_cs_flush_and_wait(struct wined3d_cs *cs) ++{ ++ BOOL fence; ++ ++ wined3d_cs_emit_fence(cs, &fence); ++ wined3d_cs_flush(cs); ++ ++ /* A busy wait should be fine, we're not supposed to have to wait very ++ * long. */ ++ while (!InterlockedCompareExchange(&fence, TRUE, TRUE)); ++} ++ ++static UINT wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data) + { + const struct wined3d_cs_present *op = data; + struct wined3d_swapchain *swapchain; +@@ -251,6 +401,8 @@ static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data) + + swapchain->swapchain_ops->swapchain_present(swapchain, + op->src_rect, op->dst_rect, op->dirty_region, op->flags); ++ ++ return sizeof(*op); + } + + void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *swapchain, +@@ -271,7 +423,7 @@ void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *sw + cs->ops->submit(cs); + } + +-static void wined3d_cs_exec_clear(struct wined3d_cs *cs, const void *data) ++static UINT wined3d_cs_exec_clear(struct wined3d_cs *cs, const void *data) + { + const struct wined3d_cs_clear *op = data; + struct wined3d_device *device; +@@ -282,6 +434,8 @@ static void wined3d_cs_exec_clear(struct wined3d_cs *cs, const void *data) + device_clear_render_targets(device, device->adapter->gl_info.limits.buffers, + &cs->state.fb, op->rect_count, op->rects, &draw_rect, op->flags, + op->color, op->depth, op->stencil); ++ ++ return sizeof(*op); + } + + void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT *rects, +@@ -301,12 +455,14 @@ void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT * + cs->ops->submit(cs); + } + +-static void wined3d_cs_exec_draw(struct wined3d_cs *cs, const void *data) ++static UINT wined3d_cs_exec_draw(struct wined3d_cs *cs, const void *data) + { + 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); ++ ++ return sizeof(*op); + } + + void wined3d_cs_emit_draw(struct wined3d_cs *cs, UINT start_idx, UINT index_count, +@@ -325,12 +481,14 @@ void wined3d_cs_emit_draw(struct wined3d_cs *cs, UINT start_idx, UINT index_coun + cs->ops->submit(cs); + } + +-static void wined3d_cs_exec_set_predication(struct wined3d_cs *cs, const void *data) ++static UINT wined3d_cs_exec_set_predication(struct wined3d_cs *cs, const void *data) + { + const struct wined3d_cs_set_predication *op = data; + + cs->state.predicate = op->predicate; + cs->state.predicate_value = op->value; ++ ++ return sizeof(*op); + } + + void wined3d_cs_emit_set_predication(struct wined3d_cs *cs, struct wined3d_query *predicate, BOOL value) +@@ -345,12 +503,14 @@ void wined3d_cs_emit_set_predication(struct wined3d_cs *cs, struct wined3d_query + cs->ops->submit(cs); + } + +-static void wined3d_cs_exec_set_viewport(struct wined3d_cs *cs, const void *data) ++static UINT 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); ++ ++ return sizeof(*op); + } + + void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport *viewport) +@@ -364,12 +524,14 @@ void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_vi + cs->ops->submit(cs); + } + +-static void wined3d_cs_exec_set_scissor_rect(struct wined3d_cs *cs, const void *data) ++static UINT 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; ++ cs->state.scissor_rect = op->rect; + device_invalidate_state(cs->device, STATE_SCISSORRECT); ++ ++ return sizeof(*op); + } + + void wined3d_cs_emit_set_scissor_rect(struct wined3d_cs *cs, const RECT *rect) +@@ -378,17 +540,19 @@ void wined3d_cs_emit_set_scissor_rect(struct wined3d_cs *cs, const RECT *rect) + + op = cs->ops->require_space(cs, sizeof(*op)); + op->opcode = WINED3D_CS_OP_SET_SCISSOR_RECT; +- op->rect = rect; ++ op->rect = *rect; + + cs->ops->submit(cs); + } + +-static void wined3d_cs_exec_set_rendertarget_view(struct wined3d_cs *cs, const void *data) ++static UINT 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); ++ ++ return sizeof(*op); + } + + void wined3d_cs_emit_set_rendertarget_view(struct wined3d_cs *cs, unsigned int view_idx, +@@ -404,7 +568,7 @@ void wined3d_cs_emit_set_rendertarget_view(struct wined3d_cs *cs, unsigned int v + cs->ops->submit(cs); + } + +-static void wined3d_cs_exec_set_depth_stencil_view(struct wined3d_cs *cs, const void *data) ++static UINT 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; +@@ -442,6 +606,8 @@ static void wined3d_cs_exec_set_depth_stencil_view(struct wined3d_cs *cs, const + } + + device_invalidate_state(device, STATE_FRAMEBUFFER); ++ ++ return sizeof(*op); + } + + void wined3d_cs_emit_set_depth_stencil_view(struct wined3d_cs *cs, struct wined3d_rendertarget_view *view) +@@ -455,12 +621,14 @@ void wined3d_cs_emit_set_depth_stencil_view(struct wined3d_cs *cs, struct wined3 + cs->ops->submit(cs); + } + +-static void wined3d_cs_exec_set_vertex_declaration(struct wined3d_cs *cs, const void *data) ++static UINT 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); ++ ++ return sizeof(*op); + } + + void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs, struct wined3d_vertex_declaration *declaration) +@@ -474,7 +642,7 @@ void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs, struct wined3 + cs->ops->submit(cs); + } + +-static void wined3d_cs_exec_set_stream_source(struct wined3d_cs *cs, const void *data) ++static UINT 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; +@@ -492,6 +660,8 @@ static void wined3d_cs_exec_set_stream_source(struct wined3d_cs *cs, const void + InterlockedDecrement(&prev->resource.bind_count); + + device_invalidate_state(cs->device, STATE_STREAMSRC); ++ ++ return sizeof(*op); + } + + void wined3d_cs_emit_set_stream_source(struct wined3d_cs *cs, UINT stream_idx, +@@ -509,7 +679,7 @@ void wined3d_cs_emit_set_stream_source(struct wined3d_cs *cs, UINT stream_idx, + cs->ops->submit(cs); + } + +-static void wined3d_cs_exec_set_stream_source_freq(struct wined3d_cs *cs, const void *data) ++static UINT 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; +@@ -519,6 +689,8 @@ static void wined3d_cs_exec_set_stream_source_freq(struct wined3d_cs *cs, const + stream->flags = op->flags; + + device_invalidate_state(cs->device, STATE_STREAMSRC); ++ ++ return sizeof(*op); + } + + void wined3d_cs_emit_set_stream_source_freq(struct wined3d_cs *cs, UINT stream_idx, UINT frequency, UINT flags) +@@ -534,7 +706,7 @@ void wined3d_cs_emit_set_stream_source_freq(struct wined3d_cs *cs, UINT stream_i + cs->ops->submit(cs); + } + +-static void wined3d_cs_exec_set_stream_output(struct wined3d_cs *cs, const void *data) ++static UINT 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; +@@ -549,6 +721,8 @@ static void wined3d_cs_exec_set_stream_output(struct wined3d_cs *cs, const void + InterlockedIncrement(&op->buffer->resource.bind_count); + if (prev) + InterlockedDecrement(&prev->resource.bind_count); ++ ++ return sizeof(*op); + } + + void wined3d_cs_emit_set_stream_output(struct wined3d_cs *cs, UINT stream_idx, +@@ -565,7 +739,7 @@ void wined3d_cs_emit_set_stream_output(struct wined3d_cs *cs, UINT stream_idx, + cs->ops->submit(cs); + } + +-static void wined3d_cs_exec_set_index_buffer(struct wined3d_cs *cs, const void *data) ++static UINT 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; +@@ -580,6 +754,8 @@ static void wined3d_cs_exec_set_index_buffer(struct wined3d_cs *cs, const void * + InterlockedDecrement(&prev->resource.bind_count); + + device_invalidate_state(cs->device, STATE_INDEXBUFFER); ++ ++ return sizeof(*op); + } + + void wined3d_cs_emit_set_index_buffer(struct wined3d_cs *cs, struct wined3d_buffer *buffer, +@@ -595,7 +771,7 @@ void wined3d_cs_emit_set_index_buffer(struct wined3d_cs *cs, struct wined3d_buff + cs->ops->submit(cs); + } + +-static void wined3d_cs_exec_set_constant_buffer(struct wined3d_cs *cs, const void *data) ++static UINT 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; +@@ -609,6 +785,7 @@ static void wined3d_cs_exec_set_constant_buffer(struct wined3d_cs *cs, const voi + InterlockedDecrement(&prev->resource.bind_count); + + device_invalidate_state(cs->device, STATE_CONSTANT_BUFFER(op->type)); ++ return sizeof(*op); + } + + void wined3d_cs_emit_set_constant_buffer(struct wined3d_cs *cs, enum wined3d_shader_type type, +@@ -625,7 +802,7 @@ void wined3d_cs_emit_set_constant_buffer(struct wined3d_cs *cs, enum wined3d_sha + cs->ops->submit(cs); + } + +-static void wined3d_cs_exec_set_texture(struct wined3d_cs *cs, const void *data) ++static UINT 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; +@@ -685,6 +862,8 @@ static void wined3d_cs_exec_set_texture(struct wined3d_cs *cs, const void *data) + } + + device_invalidate_state(cs->device, STATE_SAMPLER(op->stage)); ++ ++ return sizeof(*op); + } + + void wined3d_cs_emit_set_texture(struct wined3d_cs *cs, UINT stage, struct wined3d_texture *texture) +@@ -699,11 +878,13 @@ void wined3d_cs_emit_set_texture(struct wined3d_cs *cs, UINT stage, struct wined + cs->ops->submit(cs); + } + +-static void wined3d_cs_exec_set_shader_resource_view(struct wined3d_cs *cs, const void *data) ++static UINT 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; ++ ++ return sizeof(*op); + } + + void wined3d_cs_emit_set_shader_resource_view(struct wined3d_cs *cs, enum wined3d_shader_type type, +@@ -720,11 +901,13 @@ void wined3d_cs_emit_set_shader_resource_view(struct wined3d_cs *cs, enum wined3 + cs->ops->submit(cs); + } + +-static void wined3d_cs_exec_set_sampler(struct wined3d_cs *cs, const void *data) ++static UINT 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; ++ ++ return sizeof(*op); + } + + void wined3d_cs_emit_set_sampler(struct wined3d_cs *cs, enum wined3d_shader_type type, +@@ -741,12 +924,14 @@ void wined3d_cs_emit_set_sampler(struct wined3d_cs *cs, enum wined3d_shader_type + cs->ops->submit(cs); + } + +-static void wined3d_cs_exec_set_shader(struct wined3d_cs *cs, const void *data) ++static UINT 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)); ++ ++ return sizeof(*op); + } + + void wined3d_cs_emit_set_shader(struct wined3d_cs *cs, enum wined3d_shader_type type, struct wined3d_shader *shader) +@@ -761,12 +946,14 @@ void wined3d_cs_emit_set_shader(struct wined3d_cs *cs, enum wined3d_shader_type + cs->ops->submit(cs); + } + +-static void wined3d_cs_exec_set_render_state(struct wined3d_cs *cs, const void *data) ++static UINT 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)); ++ ++ return sizeof(*op); + } + + void wined3d_cs_emit_set_render_state(struct wined3d_cs *cs, enum wined3d_render_state state, DWORD value) +@@ -781,12 +968,14 @@ void wined3d_cs_emit_set_render_state(struct wined3d_cs *cs, enum wined3d_render + cs->ops->submit(cs); + } + +-static void wined3d_cs_exec_set_texture_state(struct wined3d_cs *cs, const void *data) ++static UINT 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)); ++ ++ return sizeof(*op); + } + + void wined3d_cs_emit_set_texture_state(struct wined3d_cs *cs, UINT stage, +@@ -803,12 +992,14 @@ void wined3d_cs_emit_set_texture_state(struct wined3d_cs *cs, UINT stage, + cs->ops->submit(cs); + } + +-static void wined3d_cs_exec_set_sampler_state(struct wined3d_cs *cs, const void *data) ++static UINT 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)); ++ ++ return sizeof(*op); + } + + void wined3d_cs_emit_set_sampler_state(struct wined3d_cs *cs, UINT sampler_idx, +@@ -825,13 +1016,15 @@ void wined3d_cs_emit_set_sampler_state(struct wined3d_cs *cs, UINT sampler_idx, + cs->ops->submit(cs); + } + +-static void wined3d_cs_exec_set_transform(struct wined3d_cs *cs, const void *data) ++static UINT 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; ++ cs->state.transforms[op->state] = op->matrix; + if (op->state < WINED3D_TS_WORLD_MATRIX(cs->device->adapter->gl_info.limits.blends)) + device_invalidate_state(cs->device, STATE_TRANSFORM(op->state)); ++ ++ return sizeof(*op); + } + + void wined3d_cs_emit_set_transform(struct wined3d_cs *cs, enum wined3d_transform_state state, +@@ -842,17 +1035,19 @@ void wined3d_cs_emit_set_transform(struct wined3d_cs *cs, enum wined3d_transform + op = cs->ops->require_space(cs, sizeof(*op)); + op->opcode = WINED3D_CS_OP_SET_TRANSFORM; + op->state = state; +- op->matrix = matrix; ++ op->matrix = *matrix; + + cs->ops->submit(cs); + } + +-static void wined3d_cs_exec_set_clip_plane(struct wined3d_cs *cs, const void *data) ++static UINT 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; ++ cs->state.clip_planes[op->plane_idx] = op->plane; + device_invalidate_state(cs->device, STATE_CLIPPLANE(op->plane_idx)); ++ ++ return sizeof(*op); + } + + void wined3d_cs_emit_set_clip_plane(struct wined3d_cs *cs, UINT plane_idx, const struct wined3d_vec4 *plane) +@@ -862,17 +1057,19 @@ void wined3d_cs_emit_set_clip_plane(struct wined3d_cs *cs, UINT plane_idx, const + op = cs->ops->require_space(cs, sizeof(*op)); + op->opcode = WINED3D_CS_OP_SET_CLIP_PLANE; + op->plane_idx = plane_idx; +- op->plane = plane; ++ op->plane = *plane; + + cs->ops->submit(cs); + } + +-static void wined3d_cs_exec_set_material(struct wined3d_cs *cs, const void *data) ++static UINT 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; ++ cs->state.material = op->material; + device_invalidate_state(cs->device, STATE_MATERIAL); ++ ++ return sizeof(*op); + } + + void wined3d_cs_emit_set_material(struct wined3d_cs *cs, const struct wined3d_material *material) +@@ -881,12 +1078,12 @@ void wined3d_cs_emit_set_material(struct wined3d_cs *cs, const struct wined3d_ma + + op = cs->ops->require_space(cs, sizeof(*op)); + op->opcode = WINED3D_CS_OP_SET_MATERIAL; +- op->material = material; ++ op->material = *material; + + cs->ops->submit(cs); + } + +-static void wined3d_cs_exec_reset_state(struct wined3d_cs *cs, const void *data) ++static UINT wined3d_cs_exec_reset_state(struct wined3d_cs *cs, const void *data) + { + struct wined3d_adapter *adapter = cs->device->adapter; + HRESULT hr; +@@ -896,6 +1093,8 @@ static void wined3d_cs_exec_reset_state(struct wined3d_cs *cs, const void *data) + if (FAILED(hr = state_init(&cs->state, &adapter->gl_info, &adapter->d3d_info, + WINED3D_STATE_NO_REF | WINED3D_STATE_INIT_DEFAULT))) + ERR("Failed to initialize CS state, hr %#x.\n", hr); ++ ++ return sizeof(struct wined3d_cs_reset_state); + } + + void wined3d_cs_emit_reset_state(struct wined3d_cs *cs) +@@ -908,8 +1107,9 @@ void wined3d_cs_emit_reset_state(struct wined3d_cs *cs) + cs->ops->submit(cs); + } + +-static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = ++static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = + { ++ /* 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, +@@ -967,6 +1167,58 @@ static const struct wined3d_cs_ops wined3d_cs_st_ops = + wined3d_cs_st_submit, + }; + ++static const struct wined3d_cs_ops wined3d_cs_mt_ops = ++{ ++ wined3d_cs_mt_require_space, ++ wined3d_cs_flush_and_wait, ++}; ++ ++/* 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_flush(cs); ++} ++ ++static DWORD WINAPI wined3d_cs_run(void *thread_param) ++{ ++ struct wined3d_cs *cs = thread_param; ++ ++ TRACE("Started.\n"); ++ ++ for (;;) ++ { ++ struct wined3d_cs_block *block; ++ UINT pos = 0; ++ ++ block = wined3d_cs_list_dequeue_blocking(&cs->exec_list); ++ while (pos < block->pos) ++ { ++ enum wined3d_cs_op opcode = *(const enum wined3d_cs_op *)&block->data[pos]; ++ ++ if (opcode >= WINED3D_CS_OP_STOP) ++ { ++ if (opcode > WINED3D_CS_OP_STOP) ++ ERR("Invalid opcode %#x.\n", opcode); ++ goto done; ++ } ++ ++ pos += wined3d_cs_op_handlers[opcode](cs, &block->data[pos]); ++ } ++ ++ wined3d_cs_list_enqueue(&cs->free_list, block); ++ } ++ ++done: ++ TRACE("Stopped.\n"); ++ return 0; ++} ++ + struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device) + { + const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; +@@ -992,12 +1244,60 @@ struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device) + return NULL; + } + ++ if ((cs->tls_idx = TlsAlloc()) == TLS_OUT_OF_INDEXES) ++ { ++ ERR("Failed to allocate cs TLS index, err %#x.\n", GetLastError()); ++ HeapFree(GetProcessHeap(), 0, cs->data); ++ HeapFree(GetProcessHeap(), 0, cs); ++ return NULL; ++ } ++ ++ if (wined3d_settings.cs_multithreaded) ++ { ++ cs->ops = &wined3d_cs_mt_ops; ++ ++ wined3d_cs_list_init(&cs->free_list); ++ wined3d_cs_list_init(&cs->exec_list); ++ ++ if (!(cs->thread = CreateThread(NULL, 0, wined3d_cs_run, cs, 0, NULL))) ++ { ++ ERR("Failed to create wined3d command stream thread.\n"); ++ if (!TlsFree(cs->tls_idx)) ++ ERR("Failed to free cs TLS index, err %#x.\n", GetLastError()); ++ HeapFree(GetProcessHeap(), 0, cs->data); ++ HeapFree(GetProcessHeap(), 0, cs); ++ return NULL; ++ } ++ } ++ + return cs; + } + + void wined3d_cs_destroy(struct wined3d_cs *cs) + { ++ DWORD ret; ++ + state_cleanup(&cs->state); ++ ++ if (wined3d_settings.cs_multithreaded) ++ { ++ wined3d_cs_emit_stop(cs); ++ ++ ret = WaitForSingleObject(cs->thread, INFINITE); ++ CloseHandle(cs->thread); ++ if (ret != WAIT_OBJECT_0) ++ ERR("Wait failed (%#x).\n", ret); ++ ++ /* FIXME: Cleanup the block lists on thread exit. */ ++#if 0 ++ wined3d_cs_list_cleanup(&cs->exec_list); ++ wined3d_cs_list_cleanup(&cs->free_list); ++#endif ++ } ++ ++ if (!TlsFree(cs->tls_idx)) ++ ERR("Failed to free cs TLS index, err %#x.\n", GetLastError()); ++ + HeapFree(GetProcessHeap(), 0, cs->data); + HeapFree(GetProcessHeap(), 0, cs); + } +diff --git a/dlls/wined3d/wined3d_main.c b/dlls/wined3d/wined3d_main.c +index 758ba43..5471e6e 100644 +--- a/dlls/wined3d/wined3d_main.c ++++ b/dlls/wined3d/wined3d_main.c +@@ -85,6 +85,7 @@ struct wined3d_settings wined3d_settings = + ~0U, /* No GS shader model limit by default. */ + ~0U, /* No PS shader model limit by default. */ + FALSE, /* 3D support enabled by default. */ ++ FALSE, /* No multithreaded CS by default. */ + }; + + struct wined3d * CDECL wined3d_create(DWORD flags) +@@ -304,6 +305,14 @@ static BOOL wined3d_dll_init(HINSTANCE hInstDLL) + TRACE("Disabling 3D support.\n"); + wined3d_settings.no_3d = TRUE; + } ++ if (!get_config_key(hkey, appkey, "CSMT", buffer, size) ++ && !strcmp(buffer,"enabled")) ++ { ++ TRACE("Enabling multithreaded command stream.\n"); ++ wined3d_settings.cs_multithreaded = TRUE; ++ TRACE("Enforcing strict draw ordering for multithreaded command stream.\n"); ++ wined3d_settings.strict_draw_ordering = TRUE; ++ } + } + + if (appkey) RegCloseKey( appkey ); +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 9c05b6c..5c5d52c 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -279,6 +279,7 @@ struct wined3d_settings + unsigned int max_sm_gs; + unsigned int max_sm_ps; + BOOL no_3d; ++ BOOL cs_multithreaded; + }; + + extern struct wined3d_settings wined3d_settings DECLSPEC_HIDDEN; +@@ -2525,6 +2526,18 @@ HRESULT state_init(struct wined3d_state *state, const struct wined3d_gl_info *gl + const struct wined3d_d3d_info *d3d_info, DWORD flags) DECLSPEC_HIDDEN; + void state_unbind_resources(struct wined3d_state *state) DECLSPEC_HIDDEN; + ++struct wined3d_cs_list ++{ ++ struct list blocks; ++}; ++ ++struct wined3d_cs_block ++{ ++ struct list entry; ++ UINT pos; ++ BYTE data[4000]; /* FIXME? The size is somewhat arbitrary. */ ++}; ++ + struct wined3d_cs_ops + { + void *(*require_space)(struct wined3d_cs *cs, size_t size); +@@ -2536,9 +2549,14 @@ struct wined3d_cs + const struct wined3d_cs_ops *ops; + struct wined3d_device *device; + struct wined3d_state state; ++ HANDLE thread; ++ DWORD tls_idx; + + size_t data_size; + void *data; ++ ++ struct wined3d_cs_list free_list; ++ struct wined3d_cs_list exec_list; + }; + + struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device) DECLSPEC_HIDDEN; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0047-wined3d-Wait-for-resource-updates-to-finish-when-usi.patch b/patches/wined3d-CSMT_Main/0047-wined3d-Wait-for-resource-updates-to-finish-when-usi.patch new file mode 100644 index 00000000..68c830d5 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0047-wined3d-Wait-for-resource-updates-to-finish-when-usi.patch @@ -0,0 +1,190 @@ +From 8eb60915d38e68c45223eafa534452fc4ffeb1fe Mon Sep 17 00:00:00 2001 +From: Henri Verbeet +Date: Sat, 8 Dec 2012 19:28:54 +0100 +Subject: wined3d: Wait for resource updates to finish when using the + multithreaded command stream. + +As opposed to just making sure they're submitted to the GPU for +"StrictDrawOrdering". This will eventually be disabled by default, but even +then it's probably useful for debugging. +--- + dlls/wined3d/arb_program_shader.c | 4 +++- + dlls/wined3d/buffer.c | 4 +++- + dlls/wined3d/device.c | 9 +++++++-- + dlls/wined3d/drawprim.c | 4 +++- + dlls/wined3d/surface.c | 28 +++++++++++++++++++++------- + dlls/wined3d/swapchain.c | 4 +++- + 6 files changed, 40 insertions(+), 13 deletions(-) + +diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c +index 2875fe1..ca456ad 100644 +--- a/dlls/wined3d/arb_program_shader.c ++++ b/dlls/wined3d/arb_program_shader.c +@@ -7679,7 +7679,9 @@ HRESULT arbfp_blit_surface(struct wined3d_device *device, DWORD filter, + /* Leave the opengl state valid for blitting */ + arbfp_blit_unset(context->gl_info); + +- if (wined3d_settings.strict_draw_ordering ++ if (wined3d_settings.cs_multithreaded) ++ context->gl_info->gl_ops.gl.p_glFinish(); ++ else if (wined3d_settings.strict_draw_ordering + || (dst_surface->container->swapchain + && (dst_surface->container->swapchain->front_buffer == dst_surface->container))) + context->gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ +diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c +index f335dfc..abad8b8 100644 +--- a/dlls/wined3d/buffer.c ++++ b/dlls/wined3d/buffer.c +@@ -1100,7 +1100,9 @@ void CDECL wined3d_buffer_unmap(struct wined3d_buffer *buffer) + } + + GL_EXTCALL(glUnmapBufferARB(buffer->buffer_type_hint)); +- if (wined3d_settings.strict_draw_ordering) ++ if (wined3d_settings.cs_multithreaded) ++ gl_info->gl_ops.gl.p_glFinish(); ++ else if (wined3d_settings.strict_draw_ordering) + gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ + context_release(context); + +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index 92478d7..08422ad 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -463,7 +463,9 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c + } + } + +- if (wined3d_settings.strict_draw_ordering || (flags & WINED3DCLEAR_TARGET ++ if (wined3d_settings.cs_multithreaded) ++ gl_info->gl_ops.gl.p_glFinish(); ++ else if (wined3d_settings.strict_draw_ordering || (flags & WINED3DCLEAR_TARGET + && target->container->swapchain && target->container->swapchain->front_buffer == target->container)) + gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ + +@@ -3247,7 +3249,10 @@ HRESULT CDECL wined3d_device_end_scene(struct wined3d_device *device) + + context = context_acquire(device, NULL); + /* We only have to do this if we need to read the, swapbuffers performs a flush for us */ +- context->gl_info->gl_ops.gl.p_glFlush(); ++ if (wined3d_settings.cs_multithreaded) ++ context->gl_info->gl_ops.gl.p_glFinish(); ++ else ++ context->gl_info->gl_ops.gl.p_glFlush(); + /* No checkGLcall here to avoid locking the lock just for checking a call that hardly ever + * fails. */ + context_release(context); +diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c +index 98261f9..d3a9e03 100644 +--- a/dlls/wined3d/drawprim.c ++++ b/dlls/wined3d/drawprim.c +@@ -781,7 +781,9 @@ void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_co + wined3d_event_query_issue(context->buffer_queries[i], device); + } + +- if (wined3d_settings.strict_draw_ordering) ++ if (wined3d_settings.cs_multithreaded) ++ gl_info->gl_ops.gl.p_glFinish(); ++ else if (wined3d_settings.strict_draw_ordering) + gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ + + context_release(context); +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 642210d..8fa2c9f 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -687,7 +687,9 @@ static void surface_depth_blt_fbo(const struct wined3d_device *device, + dst_rect->left, dst_rect->top, dst_rect->right, dst_rect->bottom, gl_mask, GL_NEAREST); + checkGLcall("glBlitFramebuffer()"); + +- if (wined3d_settings.strict_draw_ordering) ++ if (wined3d_settings.cs_multithreaded) ++ gl_info->gl_ops.gl.p_glFinish(); ++ else if (wined3d_settings.strict_draw_ordering) + gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ + + context_release(context); +@@ -816,7 +818,9 @@ static void surface_blt_fbo(const struct wined3d_device *device, + dst_rect.left, dst_rect.top, dst_rect.right, dst_rect.bottom, GL_COLOR_BUFFER_BIT, gl_filter); + checkGLcall("glBlitFramebuffer()"); + +- if (wined3d_settings.strict_draw_ordering ++ if (wined3d_settings.cs_multithreaded) ++ gl_info->gl_ops.gl.p_glFinish(); ++ else if (wined3d_settings.strict_draw_ordering + || (dst_location == WINED3D_LOCATION_DRAWABLE + && dst_surface->container->swapchain->front_buffer == dst_surface->container)) + gl_info->gl_ops.gl.p_glFlush(); +@@ -1393,7 +1397,9 @@ static void surface_upload_data(struct wined3d_surface *surface, const struct wi + checkGLcall("glBindBufferARB"); + } + +- if (wined3d_settings.strict_draw_ordering) ++ if (wined3d_settings.cs_multithreaded) ++ gl_info->gl_ops.gl.p_glFinish(); ++ else if (wined3d_settings.strict_draw_ordering) + gl_info->gl_ops.gl.p_glFlush(); + + if (gl_info->quirks & WINED3D_QUIRK_FBO_TEX_UPDATE) +@@ -3183,7 +3189,9 @@ static void fb_copy_to_texture_hwstretch(struct wined3d_surface *dst_surface, st + checkGLcall("glDeleteTextures(1, &backup)"); + } + +- if (wined3d_settings.strict_draw_ordering) ++ if (wined3d_settings.cs_multithreaded) ++ gl_info->gl_ops.gl.p_glFinish(); ++ else if (wined3d_settings.strict_draw_ordering) + gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ + + context_release(context); +@@ -3298,7 +3306,9 @@ static void surface_blt_to_drawable(const struct wined3d_device *device, + /* Leave the opengl state valid for blitting */ + device->blitter->unset_shader(context->gl_info); + +- if (wined3d_settings.strict_draw_ordering ++ if (wined3d_settings.cs_multithreaded) ++ gl_info->gl_ops.gl.p_glFinish(); ++ else if (wined3d_settings.strict_draw_ordering + || (dst_surface->container->swapchain + && dst_surface->container->swapchain->front_buffer == dst_surface->container)) + gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ +@@ -3719,7 +3729,9 @@ void surface_load_ds_location(struct wined3d_surface *surface, struct wined3d_co + + context_invalidate_state(context, STATE_FRAMEBUFFER); + +- if (wined3d_settings.strict_draw_ordering) ++ if (wined3d_settings.cs_multithreaded) ++ gl_info->gl_ops.gl.p_glFinish(); ++ else if (wined3d_settings.strict_draw_ordering) + gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ + } + else if (location == WINED3D_LOCATION_DRAWABLE) +@@ -3735,7 +3747,9 @@ void surface_load_ds_location(struct wined3d_surface *surface, struct wined3d_co + + context_invalidate_state(context, STATE_FRAMEBUFFER); + +- if (wined3d_settings.strict_draw_ordering) ++ if (wined3d_settings.cs_multithreaded) ++ gl_info->gl_ops.gl.p_glFinish(); ++ else if (wined3d_settings.strict_draw_ordering) + gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ + } + else +diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c +index ed2964e..60504ef 100644 +--- a/dlls/wined3d/swapchain.c ++++ b/dlls/wined3d/swapchain.c +@@ -531,8 +531,10 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT + swapchain_blit(swapchain, context, &src_rect, &dst_rect); + } + +- if (swapchain->num_contexts > 1) ++ if (wined3d_settings.cs_multithreaded) + gl_info->gl_ops.gl.p_glFinish(); ++ else if (swapchain->num_contexts > 1) ++ gl_info->gl_ops.gl.p_glFlush(); + + /* 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 */ +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0048-wined3d-Don-t-store-pointers-in-struct-wined3d_cs_pr.patch b/patches/wined3d-CSMT_Main/0048-wined3d-Don-t-store-pointers-in-struct-wined3d_cs_pr.patch new file mode 100644 index 00000000..3f882035 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0048-wined3d-Don-t-store-pointers-in-struct-wined3d_cs_pr.patch @@ -0,0 +1,82 @@ +From 72ea1f2801924c3856ae7a2b8045beef511b6e9e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Tue, 12 Mar 2013 11:34:58 -0700 +Subject: wined3d: Don't store pointers in struct wined3d_cs_present + +--- + dlls/wined3d/cs.c | 34 +++++++++++++++++++++++++++------- + 1 file changed, 27 insertions(+), 7 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 1122073..b30e62a 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -76,15 +76,19 @@ struct wined3d_cs_fence + BOOL *signalled; + }; + ++#define CS_PRESENT_SRC_RECT 1 ++#define CS_PRESENT_DST_RECT 2 ++#define CS_PRESENT_DIRTY_RGN 4 + 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; ++ RECT src_rect; ++ RECT dst_rect; ++ RGNDATA dirty_region; + DWORD flags; ++ DWORD set_data; + }; + + struct wined3d_cs_clear +@@ -395,12 +399,15 @@ static UINT wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data) + { + const struct wined3d_cs_present *op = data; + struct wined3d_swapchain *swapchain; ++ const RECT *src_rect = op->set_data & CS_PRESENT_SRC_RECT ? &op->src_rect : NULL; ++ const RECT *dst_rect = op->set_data & CS_PRESENT_DST_RECT ? &op->dst_rect : NULL; ++ const RGNDATA *dirty_region = op->set_data & CS_PRESENT_DIRTY_RGN ? &op->dirty_region : NULL; + + swapchain = op->swapchain; + wined3d_swapchain_set_window(swapchain, op->dst_window_override); + + swapchain->swapchain_ops->swapchain_present(swapchain, +- op->src_rect, op->dst_rect, op->dirty_region, op->flags); ++ src_rect, dst_rect, dirty_region, op->flags); + + return sizeof(*op); + } +@@ -415,9 +422,22 @@ void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *sw + 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->set_data = 0; ++ if (src_rect) ++ { ++ op->src_rect = *src_rect; ++ op->set_data |= CS_PRESENT_SRC_RECT; ++ } ++ if (dst_rect) ++ { ++ op->dst_rect = *dst_rect; ++ op->set_data |= CS_PRESENT_DST_RECT; ++ } ++ if (dirty_region) ++ { ++ op->dirty_region = *dirty_region; ++ op->set_data = CS_PRESENT_DIRTY_RGN; ++ } + op->flags = flags; + + cs->ops->submit(cs); +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0049-wined3d-Don-t-put-rectangle-pointers-into-wined3d_cs.patch b/patches/wined3d-CSMT_Main/0049-wined3d-Don-t-put-rectangle-pointers-into-wined3d_cs.patch new file mode 100644 index 00000000..dcbef3da --- /dev/null +++ b/patches/wined3d-CSMT_Main/0049-wined3d-Don-t-put-rectangle-pointers-into-wined3d_cs.patch @@ -0,0 +1,76 @@ +From 6a9d163ab416a7d1c44a11b75716ee32fb3c9f0b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Tue, 2 Apr 2013 16:17:34 +0200 +Subject: wined3d: Don't put rectangle pointers into wined3d_cs_clear + +--- + dlls/wined3d/cs.c | 13 ++++++++----- + dlls/wined3d/device.c | 2 ++ + 2 files changed, 10 insertions(+), 5 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index b30e62a..bac3fdb 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -95,11 +95,11 @@ 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; ++ RECT rects[1]; + }; + + struct wined3d_cs_draw +@@ -448,25 +448,28 @@ static UINT 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; ++ unsigned int extra_rects = op->rect_count ? op->rect_count - 1 : 0; + + device = cs->device; + wined3d_get_draw_rect(&device->state, &draw_rect); + device_clear_render_targets(device, device->adapter->gl_info.limits.buffers, +- &cs->state.fb, op->rect_count, op->rects, &draw_rect, op->flags, ++ &cs->state.fb, op->rect_count, op->rect_count ? op->rects : NULL, &draw_rect, op->flags, + op->color, op->depth, op->stencil); + +- return sizeof(*op); ++ return sizeof(*op) + sizeof(*op->rects) * extra_rects; + } + + 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) + { + struct wined3d_cs_clear *op; ++ unsigned int extra_rects = rect_count ? rect_count - 1 : 0; + +- op = cs->ops->require_space(cs, sizeof(*op)); ++ op = cs->ops->require_space(cs, sizeof(*op) + sizeof(*op->rects) * extra_rects); + op->opcode = WINED3D_CS_OP_CLEAR; + op->rect_count = rect_count; +- op->rects = rects; ++ if (rect_count) ++ memcpy(op->rects, rects, rect_count * sizeof(*rects)); + op->flags = flags; + op->color = color; + op->depth = depth; +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index 08422ad..3bb3cf0 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -3292,6 +3292,8 @@ HRESULT CDECL wined3d_device_clear(struct wined3d_device *device, DWORD rect_cou + WARN("Rects is %p, but rect_count is 0, ignoring clear\n", rects); + return WINED3D_OK; + } ++ if (rect_count && !rects) ++ rect_count = 0; + + if (flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL)) + { +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0050-wined3d-Store-the-color-in-clear-ops-instead-of-a-po.patch b/patches/wined3d-CSMT_Main/0050-wined3d-Store-the-color-in-clear-ops-instead-of-a-po.patch new file mode 100644 index 00000000..fe70d0f6 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0050-wined3d-Store-the-color-in-clear-ops-instead-of-a-po.patch @@ -0,0 +1,43 @@ +From 95126fce6331a34c71f5ff736192d25e78e67dde Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Tue, 2 Apr 2013 16:20:13 +0200 +Subject: wined3d: Store the color in clear ops instead of a pointer + +--- + dlls/wined3d/cs.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index bac3fdb..fa1ee3a 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -96,7 +96,7 @@ struct wined3d_cs_clear + enum wined3d_cs_op opcode; + DWORD rect_count; + DWORD flags; +- const struct wined3d_color *color; ++ struct wined3d_color color; + float depth; + DWORD stencil; + RECT rects[1]; +@@ -454,7 +454,7 @@ static UINT wined3d_cs_exec_clear(struct wined3d_cs *cs, const void *data) + wined3d_get_draw_rect(&device->state, &draw_rect); + device_clear_render_targets(device, device->adapter->gl_info.limits.buffers, + &cs->state.fb, op->rect_count, op->rect_count ? op->rects : NULL, &draw_rect, op->flags, +- op->color, op->depth, op->stencil); ++ &op->color, op->depth, op->stencil); + + return sizeof(*op) + sizeof(*op->rects) * extra_rects; + } +@@ -471,7 +471,7 @@ void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT * + if (rect_count) + memcpy(op->rects, rects, rect_count * sizeof(*rects)); + op->flags = flags; +- op->color = color; ++ op->color = *color; + op->depth = depth; + op->stencil = stencil; + +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0051-wined3d-Pass-the-state-to-draw_primitive.patch b/patches/wined3d-CSMT_Main/0051-wined3d-Pass-the-state-to-draw_primitive.patch new file mode 100644 index 00000000..bfc5824f --- /dev/null +++ b/patches/wined3d-CSMT_Main/0051-wined3d-Pass-the-state-to-draw_primitive.patch @@ -0,0 +1,258 @@ +From a28b86b048950e7f1bc93168bc3313eae44f82fa Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Tue, 2 Apr 2013 17:25:19 +0200 +Subject: wined3d: Pass the state to draw_primitive + +--- + dlls/wined3d/buffer.c | 6 +++--- + dlls/wined3d/context.c | 6 +++--- + dlls/wined3d/cs.c | 2 +- + dlls/wined3d/directx.c | 2 +- + dlls/wined3d/drawprim.c | 25 ++++++++++++------------- + dlls/wined3d/state.c | 4 ++-- + dlls/wined3d/utils.c | 2 +- + dlls/wined3d/wined3d_private.h | 8 +++++--- + 8 files changed, 28 insertions(+), 27 deletions(-) + +diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c +index abad8b8..8165d6b 100644 +--- a/dlls/wined3d/buffer.c ++++ b/dlls/wined3d/buffer.c +@@ -423,7 +423,7 @@ static inline void fixup_d3dcolor(DWORD *dst_color) + { + DWORD src_color = *dst_color; + +- /* Color conversion like in drawStridedSlow. watch out for little endianity ++ /* 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 + * + * 0xff000000: Alpha mask +@@ -1185,11 +1185,11 @@ static HRESULT buffer_init(struct wined3d_buffer *buffer, struct wined3d_device + + dynamic_buffer_ok = gl_info->supported[APPLE_FLUSH_BUFFER_RANGE] || gl_info->supported[ARB_MAP_BUFFER_RANGE]; + +- /* Observations show that drawStridedSlow is faster on dynamic VBs than converting + ++ /* Observations show that draw_strided_slow 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. ++ * show that draw_strided_slow is faster than converting + uploading + drawStridedFast. + * Therefore do not create a VBO for WINED3DUSAGE_DYNAMIC buffers. + */ + if (!gl_info->supported[ARB_VERTEX_BUFFER_OBJECT]) +diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c +index ffb1c43..7ba4086 100644 +--- a/dlls/wined3d/context.c ++++ b/dlls/wined3d/context.c +@@ -2896,7 +2896,7 @@ static void context_update_stream_info(struct wined3d_context *context, const st + { + if (state->vertex_declaration->half_float_conv_needed && !stream_info->all_vbo) + { +- TRACE("Using drawStridedSlow with vertex shaders for FLOAT16 conversion.\n"); ++ TRACE("Using draw_strided_slow with vertex shaders for FLOAT16 conversion.\n"); + context->use_immediate_mode_draw = TRUE; + } + else +@@ -2968,9 +2968,9 @@ static void context_preload_textures(struct wined3d_context *context, const stru + } + + /* Context activation is done by the caller. */ +-BOOL context_apply_draw_state(struct wined3d_context *context, struct wined3d_device *device) ++BOOL context_apply_draw_state(struct wined3d_context *context, const struct wined3d_device *device, ++ const struct wined3d_state *state) + { +- const struct wined3d_state *state = &device->state; + const struct StateEntry *state_table = context->state_table; + const struct wined3d_fb_state *fb = &state->fb; + unsigned int i, j; +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index fa1ee3a..eac7739 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -482,7 +482,7 @@ static UINT wined3d_cs_exec_draw(struct wined3d_cs *cs, const void *data) + { + const struct wined3d_cs_draw *op = data; + +- draw_primitive(cs->device, op->start_idx, op->index_count, ++ draw_primitive(cs->device, &cs->device->state, op->start_idx, op->index_count, + op->start_instance, op->instance_count, op->indexed); + + return sizeof(*op); +diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c +index 794496b..f7b5562 100644 +--- a/dlls/wined3d/directx.c ++++ b/dlls/wined3d/directx.c +@@ -4732,7 +4732,7 @@ static void WINE_GLAPI invalid_texcoord_func(GLenum unit, const void *data) + } + + /* Helper functions for providing vertex data to opengl. The arrays are initialized based on +- * the extension detection and are used in drawStridedSlow ++ * the extension detection and are used in draw_strided_slow + */ + static void WINE_GLAPI position_d3dcolor(const void *data) + { +diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c +index d3a9e03..1627cfa 100644 +--- a/dlls/wined3d/drawprim.c ++++ b/dlls/wined3d/drawprim.c +@@ -36,7 +36,7 @@ WINE_DECLARE_DEBUG_CHANNEL(d3d_perf); + #include + + /* Context activation is done by the caller. */ +-static void drawStridedFast(const struct wined3d_gl_info *gl_info, GLenum primitive_type, UINT count, UINT idx_size, ++static void draw_strided_fast(const struct wined3d_gl_info *gl_info, GLenum primitive_type, UINT count, UINT idx_size, + const void *idx_data, UINT start_idx, INT base_vertex_index, UINT start_instance, UINT instance_count) + { + if (idx_size) +@@ -92,7 +92,7 @@ static void drawStridedFast(const struct wined3d_gl_info *gl_info, GLenum primit + */ + + /* Context activation is done by the caller. */ +-static void drawStridedSlow(const struct wined3d_device *device, struct wined3d_context *context, ++static void draw_strided_slow(const struct wined3d_state *state, struct wined3d_context *context, + const struct wined3d_stream_info *si, UINT NumVertexes, GLenum glPrimType, + const void *idxData, UINT idxSize, UINT startIdx) + { +@@ -100,7 +100,6 @@ static void drawStridedSlow(const struct wined3d_device *device, struct wined3d_ + const WORD *pIdxBufS = NULL; + const DWORD *pIdxBufL = NULL; + UINT vx_index; +- const struct wined3d_state *state = &device->state; + LONG SkipnStrides = startIdx; + BOOL pixelShader = use_ps(state); + BOOL specular_fog = FALSE; +@@ -450,7 +449,7 @@ static inline void send_attribute(const struct wined3d_gl_info *gl_info, + } + + /* Context activation is done by the caller. */ +-static void drawStridedSlowVs(struct wined3d_context *context, const struct wined3d_state *state, ++static void draw_strided_slow_vs(struct wined3d_context *context, const struct wined3d_state *state, + const struct wined3d_stream_info *si, UINT numberOfVertices, GLenum glPrimitiveType, + const void *idxData, UINT idxSize, UINT startIdx) + { +@@ -507,7 +506,7 @@ static void drawStridedSlowVs(struct wined3d_context *context, const struct wine + } + + /* Context activation is done by the caller. */ +-static void drawStridedInstanced(struct wined3d_context *context, const struct wined3d_state *state, ++static void draw_strided_instanced(struct wined3d_context *context, const struct wined3d_state *state, + const struct wined3d_stream_info *si, UINT numberOfVertices, GLenum glPrimitiveType, + const void *idxData, UINT idxSize, UINT startIdx, UINT base_vertex_index, UINT instance_count) + { +@@ -592,10 +591,10 @@ static void remove_vbos(struct wined3d_context *context, + } + + /* Routine common to the draw primitive and draw indexed primitive routines */ +-void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_count, +- UINT start_instance, UINT instance_count, BOOL indexed) ++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) + { +- const struct wined3d_state *state = &device->state; + const struct wined3d_stream_info *stream_info; + struct wined3d_event_query *ib_query = NULL; + struct wined3d_stream_info si_emulated; +@@ -661,7 +660,7 @@ void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_co + } + } + +- if (!context_apply_draw_state(context, device)) ++ if (!context_apply_draw_state(context, device, state)) + { + context_release(context); + WARN("Unable to apply draw state, skipping draw.\n"); +@@ -753,24 +752,24 @@ void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_co + else + WARN_(d3d_perf)("Using immediate mode with vertex shaders for half float emulation.\n"); + +- drawStridedSlowVs(context, state, stream_info, index_count, ++ draw_strided_slow_vs(context, state, stream_info, index_count, + state->gl_primitive_type, idx_data, idx_size, start_idx); + } + else + { +- drawStridedSlow(device, context, stream_info, index_count, ++ draw_strided_slow(state, 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, ++ draw_strided_instanced(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, ++ draw_strided_fast(gl_info, state->gl_primitive_type, index_count, idx_size, idx_data, + start_idx, state->base_vertex_index, start_instance, instance_count); + } + +diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c +index 20f00d6..ba5c127 100644 +--- a/dlls/wined3d/state.c ++++ b/dlls/wined3d/state.c +@@ -1168,7 +1168,7 @@ void state_fog_fragpart(struct wined3d_context *context, const struct wined3d_st + + case WINED3D_FOG_NONE: + /* Both are none? According to msdn the alpha channel of the specular +- * color contains a fog factor. Set it in drawStridedSlow. ++ * color contains a fog factor. Set it in draw_strided_slow. + * Same happens with Vertexfog on transformed vertices + */ + new_source = FOGSOURCE_COORD; +@@ -4296,7 +4296,7 @@ static void load_vertex_data(struct wined3d_context *context, + } + } + } else { +- /* TODO: support blends in drawStridedSlow ++ /* TODO: support blends in draw_strided_slow + * No need to write a FIXME here, this is done after the general vertex decl decoding + */ + WARN("unsupported blending in openGl\n"); +diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c +index 8ff4e3e..389f31a 100644 +--- a/dlls/wined3d/utils.c ++++ b/dlls/wined3d/utils.c +@@ -3160,7 +3160,7 @@ void set_texture_matrix(const struct wined3d_gl_info *gl_info, const float *smat + * 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 ++ * 4th is != 1.0(opengl default). This would have to be fixed in draw_strided_slow + * or a replacement shader. */ + default: + mat[3] = mat[7] = mat[11] = 0; mat[15] = 1; +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 5c5d52c..a48cc7d 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -966,8 +966,9 @@ struct wined3d_stream_info + WORD use_map; /* MAX_ATTRIBS, 16 */ + }; + +-void draw_primitive(struct wined3d_device *device, UINT start_idx, UINT index_count, +- UINT start_instance, UINT instance_count, BOOL indexed) DECLSPEC_HIDDEN; ++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; + DWORD get_flexible_vertex_size(DWORD d3dvtVertexType) DECLSPEC_HIDDEN; + + #define eps 1e-8f +@@ -1358,7 +1359,8 @@ void context_alloc_occlusion_query(struct wined3d_context *context, + 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; +-BOOL context_apply_draw_state(struct wined3d_context *context, struct wined3d_device *device) DECLSPEC_HIDDEN; ++BOOL context_apply_draw_state(struct wined3d_context *context, const struct wined3d_device *device, ++ const struct wined3d_state *state) DECLSPEC_HIDDEN; + 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, +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0052-wined3d-Wait-for-the-cs-before-destroying-objects.patch b/patches/wined3d-CSMT_Main/0052-wined3d-Wait-for-the-cs-before-destroying-objects.patch new file mode 100644 index 00000000..2d54f2d8 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0052-wined3d-Wait-for-the-cs-before-destroying-objects.patch @@ -0,0 +1,135 @@ +From 534d7a18db58161682a42210ced42e8e7cf55ba8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Wed, 3 Apr 2013 18:01:34 +0200 +Subject: wined3d: Wait for the cs before destroying objects + +This is to avoid destroying objects that are still referenced in +commands in the cs. Later patches will migrate resource destruction to +the CS. +--- + dlls/wined3d/buffer.c | 6 ++++++ + dlls/wined3d/cs.c | 2 ++ + dlls/wined3d/shader.c | 5 +++++ + dlls/wined3d/surface.c | 6 ++++++ + dlls/wined3d/texture.c | 6 ++++++ + dlls/wined3d/vertexdeclaration.c | 5 +++++ + dlls/wined3d/wined3d_private.h | 1 + + 7 files changed, 31 insertions(+) + +diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c +index 8165d6b..bc34050 100644 +--- a/dlls/wined3d/buffer.c ++++ b/dlls/wined3d/buffer.c +@@ -552,6 +552,12 @@ ULONG CDECL wined3d_buffer_decref(struct wined3d_buffer *buffer) + + if (!refcount) + { ++ if (wined3d_settings.cs_multithreaded) ++ { ++ FIXME("Waiting for cs.\n"); ++ buffer->resource.device->cs->ops->finish(buffer->resource.device->cs); ++ } ++ + if (buffer->buffer_object) + { + context = context_acquire(buffer->resource.device, NULL); +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index eac7739..8823c9a 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -1188,12 +1188,14 @@ static const struct wined3d_cs_ops wined3d_cs_st_ops = + { + wined3d_cs_st_require_space, + wined3d_cs_st_submit, ++ wined3d_cs_st_submit, + }; + + static const struct wined3d_cs_ops wined3d_cs_mt_ops = + { + wined3d_cs_mt_require_space, + wined3d_cs_flush_and_wait, ++ wined3d_cs_flush_and_wait, + }; + + /* FIXME: wined3d_device_uninit_3d() should either flush and wait, or be an +diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c +index cc969b8..0faabaa 100644 +--- a/dlls/wined3d/shader.c ++++ b/dlls/wined3d/shader.c +@@ -1957,6 +1957,11 @@ ULONG CDECL wined3d_shader_decref(struct wined3d_shader *shader) + + if (!refcount) + { ++ if (wined3d_settings.cs_multithreaded) ++ { ++ FIXME("Waiting for cs.\n"); ++ shader->device->cs->ops->finish(shader->device->cs); ++ } + shader_cleanup(shader); + shader->parent_ops->wined3d_object_destroyed(shader->parent); + HeapFree(GetProcessHeap(), 0, shader); +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 8fa2c9f..8f8af4d 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -42,6 +42,12 @@ static void surface_cleanup(struct wined3d_surface *surface) + + TRACE("surface %p.\n", surface); + ++ if (wined3d_settings.cs_multithreaded) ++ { ++ FIXME("Waiting for cs.\n"); ++ surface->resource.device->cs->ops->finish(surface->resource.device->cs); ++ } ++ + if (surface->resource.buffer_object || surface->rb_multisample + || surface->rb_resolved || !list_empty(&surface->renderbuffers)) + { +diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c +index ec5c847..68889e5 100644 +--- a/dlls/wined3d/texture.c ++++ b/dlls/wined3d/texture.c +@@ -136,6 +136,12 @@ static void wined3d_texture_cleanup(struct wined3d_texture *texture) + + TRACE("texture %p.\n", texture); + ++ if (wined3d_settings.cs_multithreaded) ++ { ++ FIXME("Waiting for cs.\n"); ++ texture->resource.device->cs->ops->finish(texture->resource.device->cs); ++ } ++ + for (i = 0; i < sub_count; ++i) + { + struct wined3d_resource *sub_resource = texture->sub_resources[i]; +diff --git a/dlls/wined3d/vertexdeclaration.c b/dlls/wined3d/vertexdeclaration.c +index cf5378c..3f4d5e4 100644 +--- a/dlls/wined3d/vertexdeclaration.c ++++ b/dlls/wined3d/vertexdeclaration.c +@@ -56,6 +56,11 @@ ULONG CDECL wined3d_vertex_declaration_decref(struct wined3d_vertex_declaration + + if (!refcount) + { ++ if (wined3d_settings.cs_multithreaded) ++ { ++ FIXME("Waiting for cs.\n"); ++ declaration->device->cs->ops->finish(declaration->device->cs); ++ } + HeapFree(GetProcessHeap(), 0, declaration->elements); + declaration->parent_ops->wined3d_object_destroyed(declaration->parent); + HeapFree(GetProcessHeap(), 0, declaration); +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index a48cc7d..b856b6f 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2544,6 +2544,7 @@ struct wined3d_cs_ops + { + void *(*require_space)(struct wined3d_cs *cs, size_t size); + void (*submit)(struct wined3d_cs *cs); ++ void (*finish)(struct wined3d_cs *cs); + }; + + struct wined3d_cs +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0053-wined3d-Give-the-cs-its-own-state.patch b/patches/wined3d-CSMT_Main/0053-wined3d-Give-the-cs-its-own-state.patch new file mode 100644 index 00000000..2e69f234 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0053-wined3d-Give-the-cs-its-own-state.patch @@ -0,0 +1,255 @@ +From d2d8473f40a3cd357c33b4804d3b2489eaf6d979 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Tue, 1 Oct 2013 15:30:26 +0200 +Subject: wined3d: Give the cs its own state + +--- + dlls/wined3d/cs.c | 108 +++++++++++++++++++++++++++++++++++------ + dlls/wined3d/device.c | 3 ++ + dlls/wined3d/wined3d_private.h | 4 +- + 3 files changed, 99 insertions(+), 16 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 8823c9a..d252773 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -62,6 +62,7 @@ enum wined3d_cs_op + WINED3D_CS_OP_SET_CLIP_PLANE, + WINED3D_CS_OP_SET_MATERIAL, + WINED3D_CS_OP_RESET_STATE, ++ WINED3D_CS_OP_STATEBLOCK, + WINED3D_CS_OP_STOP, + }; + +@@ -268,6 +269,13 @@ struct wined3d_cs_reset_state + enum wined3d_cs_op opcode; + }; + ++struct wined3d_cs_stateblock ++{ ++ enum wined3d_cs_op opcode; ++ struct wined3d_state state; ++ float vs_consts_f[256 * 4], ps_consts_f[256 * 4]; ++}; ++ + /* FIXME: The list synchronization probably isn't particularly fast. */ + static void wined3d_cs_list_enqueue(struct wined3d_cs_list *list, struct wined3d_cs_block *block) + { +@@ -451,7 +459,7 @@ static UINT wined3d_cs_exec_clear(struct wined3d_cs *cs, const void *data) + unsigned int extra_rects = op->rect_count ? op->rect_count - 1 : 0; + + device = cs->device; +- wined3d_get_draw_rect(&device->state, &draw_rect); ++ wined3d_get_draw_rect(&cs->state, &draw_rect); + device_clear_render_targets(device, device->adapter->gl_info.limits.buffers, + &cs->state.fb, op->rect_count, op->rect_count ? op->rects : NULL, &draw_rect, op->flags, + &op->color, op->depth, op->stencil); +@@ -482,7 +490,7 @@ static UINT wined3d_cs_exec_draw(struct wined3d_cs *cs, const void *data) + { + const struct wined3d_cs_draw *op = data; + +- draw_primitive(cs->device, &cs->device->state, op->start_idx, op->index_count, ++ draw_primitive(cs->device, &cs->state, op->start_idx, op->index_count, + op->start_instance, op->instance_count, op->indexed); + + return sizeof(*op); +@@ -897,6 +905,72 @@ void wined3d_cs_emit_set_texture(struct wined3d_cs *cs, UINT stage, struct wined + op->opcode = WINED3D_CS_OP_SET_TEXTURE; + op->stage = stage; + op->texture = texture; ++ cs->ops->submit(cs); ++} ++ ++static UINT wined3d_cs_exec_transfer_stateblock(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_adapter *adapter = cs->device->adapter; ++ const struct wined3d_cs_stateblock *op = data; ++ UINT num_vs_consts_f = sizeof(op->vs_consts_f) / sizeof(*op->vs_consts_f) / 4; ++ UINT num_ps_consts_f = sizeof(op->ps_consts_f) / sizeof(*op->ps_consts_f) / 4; ++ ++ num_vs_consts_f = min(num_vs_consts_f, adapter->d3d_info.limits.vs_uniform_count); ++ num_ps_consts_f = min(num_ps_consts_f, adapter->d3d_info.limits.ps_uniform_count); ++ ++ /* Don't memcpy the entire struct, we'll remove single items as we add dedicated ++ * ops for setting states */ ++ ++ cs->state.base_vertex_index = op->state.base_vertex_index; ++ cs->state.load_base_vertex_index = op->state.load_base_vertex_index; ++ cs->state.gl_primitive_type = op->state.gl_primitive_type; ++ ++ memcpy(cs->state.vs_consts_b, op->state.vs_consts_b, sizeof(cs->state.vs_consts_b)); ++ memcpy(cs->state.vs_consts_i, op->state.vs_consts_i, sizeof(cs->state.vs_consts_i)); ++ memcpy(cs->state.vs_consts_f, op->state.vs_consts_f, sizeof(*cs->state.vs_consts_f) * num_vs_consts_f); ++ ++ memcpy(cs->state.ps_consts_b, op->state.ps_consts_b, sizeof(cs->state.ps_consts_b)); ++ memcpy(cs->state.ps_consts_i, op->state.ps_consts_i, sizeof(cs->state.ps_consts_i)); ++ memcpy(cs->state.ps_consts_f, op->state.ps_consts_f, sizeof(*cs->state.ps_consts_f) * num_ps_consts_f); ++ ++ memcpy(cs->state.lights, op->state.lights, sizeof(cs->state.lights)); ++ ++ return sizeof(*op); ++} ++ ++void wined3d_cs_emit_transfer_stateblock(struct wined3d_cs *cs, const struct wined3d_state *state) ++{ ++ const struct wined3d_device *device = cs->device; ++ const struct wined3d_adapter *adapter = device->adapter; ++ struct wined3d_cs_stateblock *op; ++ UINT num_vs_consts_f = sizeof(op->vs_consts_f) / sizeof(*op->vs_consts_f) / 4; ++ UINT num_ps_consts_f = sizeof(op->ps_consts_f) / sizeof(*op->ps_consts_f) / 4; ++ ++ num_vs_consts_f = min(num_vs_consts_f, adapter->d3d_info.limits.vs_uniform_count); ++ num_ps_consts_f = min(num_ps_consts_f, adapter->d3d_info.limits.ps_uniform_count); ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_STATEBLOCK; ++ ++ /* Don't memcpy the entire struct, we'll remove single items as we add dedicated ++ * ops for setting states */ ++ op->state.base_vertex_index = state->base_vertex_index; ++ op->state.load_base_vertex_index = state->load_base_vertex_index; ++ op->state.gl_primitive_type = state->gl_primitive_type; ++ ++ memcpy(op->state.vs_consts_b, state->vs_consts_b, sizeof(op->state.vs_consts_b)); ++ memcpy(op->state.vs_consts_i, state->vs_consts_i, sizeof(op->state.vs_consts_i)); ++ op->state.vs_consts_f = op->vs_consts_f; ++ memcpy(op->state.vs_consts_f, state->vs_consts_f, sizeof(*op->state.vs_consts_f) * num_vs_consts_f); ++ ++ memcpy(op->state.ps_consts_b, state->ps_consts_b, sizeof(op->state.ps_consts_b)); ++ memcpy(op->state.ps_consts_i, state->ps_consts_i, sizeof(op->state.ps_consts_i)); ++ op->state.ps_consts_f = op->ps_consts_f; ++ memcpy(op->state.ps_consts_f, state->ps_consts_f, sizeof(*op->state.ps_consts_f) * num_ps_consts_f); ++ ++ /* FIXME: This is not ideal. CS is still running synchronously, so this is ok. ++ * It will go away soon anyway. */ ++ memcpy(op->state.lights, state->lights, sizeof(op->state.lights)); + + cs->ops->submit(cs); + } +@@ -1158,6 +1232,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* WINED3D_CS_OP_SET_CLIP_PLANE */ wined3d_cs_exec_set_clip_plane, + /* WINED3D_CS_OP_SET_MATERIAL */ wined3d_cs_exec_set_material, + /* WINED3D_CS_OP_RESET_STATE */ wined3d_cs_exec_reset_state, ++ /* WINED3D_CS_OP_STATEBLOCK */ wined3d_cs_exec_transfer_stateblock, + }; + + static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size) +@@ -1247,7 +1322,7 @@ done: + 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; ++ struct wined3d_cs *cs = NULL; + + if (!(cs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*cs)))) + return NULL; +@@ -1255,8 +1330,7 @@ struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device) + if (FAILED(state_init(&cs->state, gl_info, &device->adapter->d3d_info, + WINED3D_STATE_NO_REF | WINED3D_STATE_INIT_DEFAULT))) + { +- HeapFree(GetProcessHeap(), 0, cs); +- return NULL; ++ goto err; + } + + cs->ops = &wined3d_cs_st_ops; +@@ -1265,16 +1339,13 @@ struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device) + cs->data_size = WINED3D_INITIAL_CS_SIZE; + if (!(cs->data = HeapAlloc(GetProcessHeap(), 0, cs->data_size))) + { +- HeapFree(GetProcessHeap(), 0, cs); +- return NULL; ++ goto err; + } + + if ((cs->tls_idx = TlsAlloc()) == TLS_OUT_OF_INDEXES) + { + ERR("Failed to allocate cs TLS index, err %#x.\n", GetLastError()); +- HeapFree(GetProcessHeap(), 0, cs->data); +- HeapFree(GetProcessHeap(), 0, cs); +- return NULL; ++ goto err; + } + + if (wined3d_settings.cs_multithreaded) +@@ -1287,15 +1358,22 @@ struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device) + if (!(cs->thread = CreateThread(NULL, 0, wined3d_cs_run, cs, 0, NULL))) + { + ERR("Failed to create wined3d command stream thread.\n"); +- if (!TlsFree(cs->tls_idx)) +- ERR("Failed to free cs TLS index, err %#x.\n", GetLastError()); +- HeapFree(GetProcessHeap(), 0, cs->data); +- HeapFree(GetProcessHeap(), 0, cs); +- return NULL; ++ goto err; + } + } + + return cs; ++ ++err: ++ if (cs) ++ { ++ state_cleanup(&cs->state); ++ if (cs->tls_idx != TLS_OUT_OF_INDEXES && !TlsFree(cs->tls_idx)) ++ ERR("Failed to free cs TLS index, err %#x.\n", GetLastError()); ++ HeapFree(GetProcessHeap(), 0, cs->data); ++ } ++ HeapFree(GetProcessHeap(), 0, cs); ++ return NULL; + } + + void wined3d_cs_destroy(struct wined3d_cs *cs) +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index 3bb3cf0..6ea0b9a 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -3391,6 +3391,7 @@ HRESULT CDECL wined3d_device_draw_primitive(struct wined3d_device *device, UINT + device_invalidate_state(device, STATE_BASEVERTEXINDEX); + } + ++ wined3d_cs_emit_transfer_stateblock(device->cs, &device->state); + wined3d_cs_emit_draw(device->cs, start_vertex, vertex_count, 0, 0, FALSE); + + return WINED3D_OK; +@@ -3425,6 +3426,7 @@ HRESULT CDECL wined3d_device_draw_indexed_primitive(struct wined3d_device *devic + device_invalidate_state(device, STATE_BASEVERTEXINDEX); + } + ++ wined3d_cs_emit_transfer_stateblock(device->cs, &device->state); + wined3d_cs_emit_draw(device->cs, start_idx, index_count, 0, 0, TRUE); + + return WINED3D_OK; +@@ -3435,6 +3437,7 @@ void CDECL wined3d_device_draw_indexed_primitive_instanced(struct wined3d_device + { + TRACE("device %p, start_idx %u, index_count %u.\n", device, start_idx, index_count); + ++ wined3d_cs_emit_transfer_stateblock(device->cs, &device->state); + wined3d_cs_emit_draw(device->cs, start_idx, index_count, start_instance, instance_count, TRUE); + } + +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index b856b6f..02104ce 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2537,7 +2537,7 @@ struct wined3d_cs_block + { + struct list entry; + UINT pos; +- BYTE data[4000]; /* FIXME? The size is somewhat arbitrary. */ ++ BYTE data[sizeof(struct wined3d_state) * 2]; /* FIXME? The size is somewhat arbitrary. */ + }; + + struct wined3d_cs_ops +@@ -2577,6 +2577,8 @@ void wined3d_cs_emit_set_clip_plane(struct wined3d_cs *cs, UINT plane_idx, + const struct wined3d_vec4 *plane) DECLSPEC_HIDDEN; + void wined3d_cs_emit_set_constant_buffer(struct wined3d_cs *cs, enum wined3d_shader_type type, + UINT cb_idx, struct wined3d_buffer *buffer) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_transfer_stateblock(struct wined3d_cs *cs, ++ const struct wined3d_state *state) DECLSPEC_HIDDEN; + void wined3d_cs_emit_set_depth_stencil_view(struct wined3d_cs *cs, + struct wined3d_rendertarget_view *view) DECLSPEC_HIDDEN; + void wined3d_cs_emit_set_index_buffer(struct wined3d_cs *cs, struct wined3d_buffer *buffer, +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0054-wined3d-Send-float-constant-updates-through-the-comm.patch b/patches/wined3d-CSMT_Main/0054-wined3d-Send-float-constant-updates-through-the-comm.patch new file mode 100644 index 00000000..a7e95504 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0054-wined3d-Send-float-constant-updates-through-the-comm.patch @@ -0,0 +1,208 @@ +From bbd02a077bf5ba977724ada68709f46150e482fb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Tue, 20 Aug 2013 15:12:26 +0200 +Subject: wined3d: Send float constant updates through the command stream + +--- + dlls/wined3d/cs.c | 88 ++++++++++++++++++++++++++++++++---------- + dlls/wined3d/device.c | 7 ++-- + dlls/wined3d/wined3d_private.h | 2 + + 3 files changed, 74 insertions(+), 23 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index d252773..56cbcb6 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -63,6 +63,8 @@ enum wined3d_cs_op + WINED3D_CS_OP_SET_MATERIAL, + WINED3D_CS_OP_RESET_STATE, + WINED3D_CS_OP_STATEBLOCK, ++ WINED3D_CS_OP_SET_VS_CONSTS_F, ++ WINED3D_CS_OP_SET_PS_CONSTS_F, + WINED3D_CS_OP_STOP, + }; + +@@ -273,7 +275,13 @@ struct wined3d_cs_stateblock + { + enum wined3d_cs_op opcode; + struct wined3d_state state; +- float vs_consts_f[256 * 4], ps_consts_f[256 * 4]; ++}; ++ ++struct wined3d_cs_set_consts_f ++{ ++ enum wined3d_cs_op opcode; ++ UINT start_register, vector4f_count; ++ float constants[4]; + }; + + /* FIXME: The list synchronization probably isn't particularly fast. */ +@@ -910,13 +918,7 @@ void wined3d_cs_emit_set_texture(struct wined3d_cs *cs, UINT stage, struct wined + + static UINT wined3d_cs_exec_transfer_stateblock(struct wined3d_cs *cs, const void *data) + { +- const struct wined3d_adapter *adapter = cs->device->adapter; + const struct wined3d_cs_stateblock *op = data; +- UINT num_vs_consts_f = sizeof(op->vs_consts_f) / sizeof(*op->vs_consts_f) / 4; +- UINT num_ps_consts_f = sizeof(op->ps_consts_f) / sizeof(*op->ps_consts_f) / 4; +- +- num_vs_consts_f = min(num_vs_consts_f, adapter->d3d_info.limits.vs_uniform_count); +- num_ps_consts_f = min(num_ps_consts_f, adapter->d3d_info.limits.ps_uniform_count); + + /* Don't memcpy the entire struct, we'll remove single items as we add dedicated + * ops for setting states */ +@@ -927,11 +929,9 @@ static UINT wined3d_cs_exec_transfer_stateblock(struct wined3d_cs *cs, const voi + + memcpy(cs->state.vs_consts_b, op->state.vs_consts_b, sizeof(cs->state.vs_consts_b)); + memcpy(cs->state.vs_consts_i, op->state.vs_consts_i, sizeof(cs->state.vs_consts_i)); +- memcpy(cs->state.vs_consts_f, op->state.vs_consts_f, sizeof(*cs->state.vs_consts_f) * num_vs_consts_f); + + memcpy(cs->state.ps_consts_b, op->state.ps_consts_b, sizeof(cs->state.ps_consts_b)); + memcpy(cs->state.ps_consts_i, op->state.ps_consts_i, sizeof(cs->state.ps_consts_i)); +- memcpy(cs->state.ps_consts_f, op->state.ps_consts_f, sizeof(*cs->state.ps_consts_f) * num_ps_consts_f); + + memcpy(cs->state.lights, op->state.lights, sizeof(cs->state.lights)); + +@@ -940,14 +940,7 @@ static UINT wined3d_cs_exec_transfer_stateblock(struct wined3d_cs *cs, const voi + + void wined3d_cs_emit_transfer_stateblock(struct wined3d_cs *cs, const struct wined3d_state *state) + { +- const struct wined3d_device *device = cs->device; +- const struct wined3d_adapter *adapter = device->adapter; + struct wined3d_cs_stateblock *op; +- UINT num_vs_consts_f = sizeof(op->vs_consts_f) / sizeof(*op->vs_consts_f) / 4; +- UINT num_ps_consts_f = sizeof(op->ps_consts_f) / sizeof(*op->ps_consts_f) / 4; +- +- num_vs_consts_f = min(num_vs_consts_f, adapter->d3d_info.limits.vs_uniform_count); +- num_ps_consts_f = min(num_ps_consts_f, adapter->d3d_info.limits.ps_uniform_count); + + op = cs->ops->require_space(cs, sizeof(*op)); + op->opcode = WINED3D_CS_OP_STATEBLOCK; +@@ -960,13 +953,9 @@ void wined3d_cs_emit_transfer_stateblock(struct wined3d_cs *cs, const struct win + + memcpy(op->state.vs_consts_b, state->vs_consts_b, sizeof(op->state.vs_consts_b)); + memcpy(op->state.vs_consts_i, state->vs_consts_i, sizeof(op->state.vs_consts_i)); +- op->state.vs_consts_f = op->vs_consts_f; +- memcpy(op->state.vs_consts_f, state->vs_consts_f, sizeof(*op->state.vs_consts_f) * num_vs_consts_f); + + memcpy(op->state.ps_consts_b, state->ps_consts_b, sizeof(op->state.ps_consts_b)); + memcpy(op->state.ps_consts_i, state->ps_consts_i, sizeof(op->state.ps_consts_i)); +- op->state.ps_consts_f = op->ps_consts_f; +- memcpy(op->state.ps_consts_f, state->ps_consts_f, sizeof(*op->state.ps_consts_f) * num_ps_consts_f); + + /* FIXME: This is not ideal. CS is still running synchronously, so this is ok. + * It will go away soon anyway. */ +@@ -1039,6 +1028,63 @@ void wined3d_cs_emit_set_shader(struct wined3d_cs *cs, enum wined3d_shader_type + op->opcode = WINED3D_CS_OP_SET_SHADER; + op->type = type; + op->shader = shader; ++} ++ ++static UINT wined3d_cs_exec_set_vs_consts_f(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_set_consts_f *op = data; ++ struct wined3d_device *device = cs->device; ++ ++ memcpy(cs->state.vs_consts_f + op->start_register * 4, op->constants, ++ sizeof(*cs->state.vs_consts_f) * 4 * op->vector4f_count); ++ ++ device->shader_backend->shader_update_float_vertex_constants(device, ++ op->start_register, op->vector4f_count); ++ ++ return sizeof(*op) + sizeof(op->constants) * (op->vector4f_count - 1); ++} ++ ++static UINT wined3d_cs_exec_set_ps_consts_f(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_set_consts_f *op = data; ++ struct wined3d_device *device = cs->device; ++ ++ memcpy(cs->state.ps_consts_f + op->start_register * 4, op->constants, ++ sizeof(*cs->state.ps_consts_f) * 4 * op->vector4f_count); ++ ++ device->shader_backend->shader_update_float_pixel_constants(device, ++ op->start_register, op->vector4f_count); ++ ++ return sizeof(*op) + sizeof(op->constants) * (op->vector4f_count - 1); ++} ++ ++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) ++{ ++ struct wined3d_cs_set_consts_f *op; ++ UINT extra_space = vector4f_count - 1; ++ ++ op = cs->ops->require_space(cs, sizeof(*op) + sizeof(op->constants) * extra_space); ++ switch (type) ++ { ++ case WINED3D_SHADER_TYPE_PIXEL: ++ op->opcode = WINED3D_CS_OP_SET_PS_CONSTS_F; ++ break; ++ ++ case WINED3D_SHADER_TYPE_VERTEX: ++ op->opcode = WINED3D_CS_OP_SET_VS_CONSTS_F; ++ break; ++ ++ case WINED3D_SHADER_TYPE_GEOMETRY: ++ FIXME("Invalid for geometry shaders\n"); ++ return; ++ ++ case WINED3D_SHADER_TYPE_COUNT: ++ break; ++ } ++ op->start_register = start_register; ++ op->vector4f_count = vector4f_count; ++ memcpy(op->constants, constants, sizeof(*constants) * 4 * vector4f_count); + + cs->ops->submit(cs); + } +@@ -1233,6 +1279,8 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* WINED3D_CS_OP_SET_MATERIAL */ wined3d_cs_exec_set_material, + /* WINED3D_CS_OP_RESET_STATE */ wined3d_cs_exec_reset_state, + /* WINED3D_CS_OP_STATEBLOCK */ wined3d_cs_exec_transfer_stateblock, ++ /* WINED3D_CS_OP_SET_VS_CONSTS_F */ wined3d_cs_exec_set_vs_consts_f, ++ /* WINED3D_CS_OP_SET_PS_CONSTS_F */ wined3d_cs_exec_set_ps_consts_f, + }; + + static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size) +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index 6ea0b9a..2aba2a4 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -2341,8 +2341,8 @@ HRESULT CDECL wined3d_device_set_vs_consts_f(struct wined3d_device *device, + memset(device->recording->changed.vertexShaderConstantsF + start_register, 1, + sizeof(*device->recording->changed.vertexShaderConstantsF) * vector4f_count); + else +- device->shader_backend->shader_update_float_vertex_constants(device, start_register, vector4f_count); +- ++ wined3d_cs_emit_set_consts_f(device->cs, start_register, constants, vector4f_count, ++ WINED3D_SHADER_TYPE_VERTEX); + + return WINED3D_OK; + } +@@ -2576,7 +2576,8 @@ HRESULT CDECL wined3d_device_set_ps_consts_f(struct wined3d_device *device, + memset(device->recording->changed.pixelShaderConstantsF + start_register, 1, + sizeof(*device->recording->changed.pixelShaderConstantsF) * vector4f_count); + else +- device->shader_backend->shader_update_float_pixel_constants(device, start_register, vector4f_count); ++ wined3d_cs_emit_set_consts_f(device->cs, start_register, constants, vector4f_count, ++ WINED3D_SHADER_TYPE_PIXEL); + + return WINED3D_OK; + } +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 02104ce..d673a8f 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2613,6 +2613,8 @@ void wined3d_cs_emit_set_transform(struct wined3d_cs *cs, enum wined3d_transform + 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; ++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; + + /* 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 +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0055-wined3d-Request-a-glFinish-before-modifying-resource.patch b/patches/wined3d-CSMT_Main/0055-wined3d-Request-a-glFinish-before-modifying-resource.patch new file mode 100644 index 00000000..120fead2 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0055-wined3d-Request-a-glFinish-before-modifying-resource.patch @@ -0,0 +1,253 @@ +From e6796ac98c5263a0cec410ecaf7392f2a22ff4da Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 4 Apr 2013 11:50:09 +0200 +Subject: wined3d: Request a glFinish before modifying resources outside the cs + +--- + dlls/wined3d/buffer.c | 17 +++++++++++++++++ + dlls/wined3d/cs.c | 30 ++++++++++++++++++++++++++++++ + dlls/wined3d/device.c | 42 ++++++++++++++++++++++++++++++++++++++++++ + dlls/wined3d/resource.c | 7 +++++++ + dlls/wined3d/surface.c | 7 +++++++ + dlls/wined3d/wined3d_private.h | 1 + + 6 files changed, 104 insertions(+) + +diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c +index bc34050..d2c1d62 100644 +--- a/dlls/wined3d/buffer.c ++++ b/dlls/wined3d/buffer.c +@@ -931,6 +931,15 @@ void buffer_internal_preload(struct wined3d_buffer *buffer, struct wined3d_conte + void CDECL wined3d_buffer_preload(struct wined3d_buffer *buffer) + { + struct wined3d_context *context; ++ struct wined3d_device *device = buffer->resource.device; ++ ++ if (wined3d_settings.cs_multithreaded) ++ { ++ FIXME("Waiting for cs.\n"); ++ wined3d_cs_emit_glfinish(device->cs); ++ device->cs->ops->finish(device->cs); ++ } ++ + context = context_acquire(buffer->resource.device, NULL); + buffer_internal_preload(buffer, context, NULL); + context_release(context); +@@ -947,9 +956,17 @@ HRESULT CDECL wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UIN + { + LONG count; + BYTE *base; ++ struct wined3d_device *device = buffer->resource.device; + + TRACE("buffer %p, offset %u, size %u, data %p, flags %#x\n", buffer, offset, size, data, flags); + ++ if (wined3d_settings.cs_multithreaded) ++ { ++ FIXME("Waiting for cs.\n"); ++ wined3d_cs_emit_glfinish(device->cs); ++ device->cs->ops->finish(device->cs); ++ } ++ + flags = wined3d_resource_sanitize_map_flags(&buffer->resource, flags); + /* Filter redundant WINED3D_MAP_DISCARD maps. The 3DMark2001 multitexture + * fill rate test seems to depend on this. When we map a buffer with +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 56cbcb6..8b24e73 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -65,6 +65,7 @@ enum wined3d_cs_op + WINED3D_CS_OP_STATEBLOCK, + WINED3D_CS_OP_SET_VS_CONSTS_F, + WINED3D_CS_OP_SET_PS_CONSTS_F, ++ WINED3D_CS_OP_GLFINISH, + WINED3D_CS_OP_STOP, + }; + +@@ -284,6 +285,11 @@ struct wined3d_cs_set_consts_f + float constants[4]; + }; + ++struct wined3d_cs_finish ++{ ++ enum wined3d_cs_op opcode; ++}; ++ + /* FIXME: The list synchronization probably isn't particularly fast. */ + static void wined3d_cs_list_enqueue(struct wined3d_cs_list *list, struct wined3d_cs_block *block) + { +@@ -1250,6 +1256,29 @@ void wined3d_cs_emit_reset_state(struct wined3d_cs *cs) + cs->ops->submit(cs); + } + ++static UINT wined3d_cs_exec_glfinish(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_finish *op = data; ++ struct wined3d_device *device = cs->device; ++ struct wined3d_context *context; ++ ++ context = context_acquire(device, NULL); ++ context->gl_info->gl_ops.gl.p_glFinish(); ++ context_release(context); ++ ++ return sizeof(*op); ++} ++ ++void wined3d_cs_emit_glfinish(struct wined3d_cs *cs) ++{ ++ struct wined3d_cs_finish *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_GLFINISH; ++ ++ cs->ops->submit(cs); ++} ++ + static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = + { + /* WINED3D_CS_OP_FENCE */ wined3d_cs_exec_fence, +@@ -1281,6 +1310,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* WINED3D_CS_OP_STATEBLOCK */ wined3d_cs_exec_transfer_stateblock, + /* WINED3D_CS_OP_SET_VS_CONSTS_F */ wined3d_cs_exec_set_vs_consts_f, + /* WINED3D_CS_OP_SET_PS_CONSTS_F */ wined3d_cs_exec_set_ps_consts_f, ++ /* WINED3D_CS_OP_GLFINISH */ wined3d_cs_exec_glfinish, + }; + + static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size) +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index 2aba2a4..4d15518 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -2737,6 +2737,13 @@ static HRESULT process_vertices_strided(const struct wined3d_device *device, DWO + return hr; + } + ++ if (wined3d_settings.cs_multithreaded) ++ { ++ FIXME("Waiting for cs.\n"); ++ wined3d_cs_emit_glfinish(device->cs); ++ device->cs->ops->finish(device->cs); ++ } ++ + wined3d_device_get_transform(device, WINED3D_TS_VIEW, &view_mat); + wined3d_device_get_transform(device, WINED3D_TS_PROJECTION, &proj_mat); + wined3d_device_get_transform(device, WINED3D_TS_WORLD_MATRIX(0), &world_mat); +@@ -3531,6 +3538,13 @@ HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device, + return WINED3DERR_INVALIDCALL; + } + ++ if (wined3d_settings.cs_multithreaded) ++ { ++ FIXME("Waiting for cs.\n"); ++ wined3d_cs_emit_glfinish(device->cs); ++ device->cs->ops->finish(device->cs); ++ } ++ + /* Make sure that the destination texture is loaded. */ + context = context_acquire(device, NULL); + wined3d_texture_load(dst_texture, context, FALSE); +@@ -3768,6 +3782,13 @@ HRESULT CDECL wined3d_device_update_surface(struct wined3d_device *device, + return WINED3DERR_INVALIDCALL; + } + ++ if (wined3d_settings.cs_multithreaded) ++ { ++ FIXME("Waiting for cs.\n"); ++ wined3d_cs_emit_glfinish(device->cs); ++ device->cs->ops->finish(device->cs); ++ } ++ + return surface_upload_from_surface(dst_surface, dst_point, src_surface, src_rect); + } + +@@ -3870,6 +3891,13 @@ HRESULT CDECL wined3d_device_clear_rendertarget_view(struct wined3d_device *devi + rect = &r; + } + ++ if (wined3d_settings.cs_multithreaded) ++ { ++ FIXME("Waiting for cs.\n"); ++ wined3d_cs_emit_glfinish(device->cs); ++ device->cs->ops->finish(device->cs); ++ } ++ + resource = wined3d_texture_get_sub_resource(wined3d_texture_from_resource(resource), view->sub_resource_idx); + + return surface_color_fill(surface_from_resource(resource), rect, color); +@@ -4200,6 +4228,13 @@ void CDECL wined3d_device_evict_managed_resources(struct wined3d_device *device) + + TRACE("device %p.\n", device); + ++ if (wined3d_settings.cs_multithreaded) ++ { ++ FIXME("Waiting for cs.\n"); ++ wined3d_cs_emit_glfinish(device->cs); ++ device->cs->ops->finish(device->cs); ++ } ++ + LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &device->resources, struct wined3d_resource, resource_list_entry) + { + TRACE("Checking resource %p for eviction.\n", resource); +@@ -4324,6 +4359,13 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device, + + TRACE("device %p, swapchain_desc %p, mode %p, callback %p.\n", device, swapchain_desc, mode, callback); + ++ if (wined3d_settings.cs_multithreaded) ++ { ++ FIXME("Waiting for cs.\n"); ++ wined3d_cs_emit_glfinish(device->cs); ++ device->cs->ops->finish(device->cs); ++ } ++ + if (!(swapchain = wined3d_device_get_swapchain(device, 0))) + { + ERR("Failed to get the first implicit swapchain.\n"); +diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c +index 8486dc3..bf228d1 100644 +--- a/dlls/wined3d/resource.c ++++ b/dlls/wined3d/resource.c +@@ -702,6 +702,13 @@ HRESULT wined3d_resource_map(struct wined3d_resource *resource, + + flags = wined3d_resource_sanitize_map_flags(resource, flags); + ++ if (wined3d_settings.cs_multithreaded) ++ { ++ FIXME("Waiting for cs.\n"); ++ wined3d_cs_emit_glfinish(device->cs); ++ device->cs->ops->finish(device->cs); ++ } ++ + if (device->d3d_initialized) + context = context_acquire(device, NULL); + +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 8f8af4d..97450ef 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -5051,6 +5051,13 @@ HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const REC + flags &= ~WINEDDBLT_DONOTWAIT; + } + ++ if (wined3d_settings.cs_multithreaded) ++ { ++ FIXME("Waiting for cs.\n"); ++ wined3d_cs_emit_glfinish(device->cs); ++ device->cs->ops->finish(device->cs); ++ } ++ + if (!device->d3d_initialized) + { + WARN("D3D not initialized, using fallback.\n"); +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index d673a8f..ba0ce26 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2615,6 +2615,7 @@ void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs, + void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport *viewport) DECLSPEC_HIDDEN; + 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_glfinish(struct wined3d_cs *cs) DECLSPEC_HIDDEN; + + /* 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 +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0056-wined3d-Finish-the-cs-before-changing-the-texture-lo.patch b/patches/wined3d-CSMT_Main/0056-wined3d-Finish-the-cs-before-changing-the-texture-lo.patch new file mode 100644 index 00000000..d67ea21d --- /dev/null +++ b/patches/wined3d-CSMT_Main/0056-wined3d-Finish-the-cs-before-changing-the-texture-lo.patch @@ -0,0 +1,30 @@ +From 64d0e5c85cdd399857597ab57cfd4e2444e17226 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Wed, 10 Apr 2013 19:53:44 +0200 +Subject: wined3d: Finish the cs before changing the texture lod + +--- + dlls/wined3d/texture.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c +index 68889e5..8212c96 100644 +--- a/dlls/wined3d/texture.c ++++ b/dlls/wined3d/texture.c +@@ -601,6 +601,13 @@ DWORD CDECL wined3d_texture_set_lod(struct wined3d_texture *texture, DWORD lod) + + if (texture->lod != lod) + { ++ if (wined3d_settings.cs_multithreaded) ++ { ++ struct wined3d_device *device = texture->resource.device; ++ FIXME("Waiting for cs.\n"); ++ device->cs->ops->finish(device->cs); ++ } ++ + texture->lod = lod; + + texture->texture_rgb.states[WINED3DTEXSTA_MAXMIPLEVEL] = ~0U; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0057-wined3d-Don-t-call-glFinish-after-clears.patch b/patches/wined3d-CSMT_Main/0057-wined3d-Don-t-call-glFinish-after-clears.patch new file mode 100644 index 00000000..793b0ec0 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0057-wined3d-Don-t-call-glFinish-after-clears.patch @@ -0,0 +1,27 @@ +From d4014863c602be40898af0f2be9b718ee6abe7d0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 4 Apr 2013 11:51:13 +0200 +Subject: wined3d: Don't call glFinish after clears + +--- + dlls/wined3d/device.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index 4d15518..98c0717 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -463,9 +463,7 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c + } + } + +- if (wined3d_settings.cs_multithreaded) +- gl_info->gl_ops.gl.p_glFinish(); +- else if (wined3d_settings.strict_draw_ordering || (flags & WINED3DCLEAR_TARGET ++ if (wined3d_settings.strict_draw_ordering || (flags & WINED3DCLEAR_TARGET + && target->container->swapchain && target->container->swapchain->front_buffer == target->container)) + gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ + +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0058-wined3d-Don-t-call-glFinish-after-draws.patch b/patches/wined3d-CSMT_Main/0058-wined3d-Don-t-call-glFinish-after-draws.patch new file mode 100644 index 00000000..cdc804f1 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0058-wined3d-Don-t-call-glFinish-after-draws.patch @@ -0,0 +1,27 @@ +From 7fd4d602c8a324c5f474370457363910e074296f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 4 Apr 2013 11:53:10 +0200 +Subject: wined3d: Don't call glFinish after draws + +--- + dlls/wined3d/drawprim.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c +index 1627cfa..43d867d 100644 +--- a/dlls/wined3d/drawprim.c ++++ b/dlls/wined3d/drawprim.c +@@ -780,9 +780,7 @@ void draw_primitive(struct wined3d_device *device, const struct wined3d_state *s + wined3d_event_query_issue(context->buffer_queries[i], device); + } + +- if (wined3d_settings.cs_multithreaded) +- gl_info->gl_ops.gl.p_glFinish(); +- else if (wined3d_settings.strict_draw_ordering) ++ if (wined3d_settings.strict_draw_ordering) + gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ + + context_release(context); +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0059-wined3d-Shadow-device-offscreenBuffer-in-the-context.patch b/patches/wined3d-CSMT_Main/0059-wined3d-Shadow-device-offscreenBuffer-in-the-context.patch new file mode 100644 index 00000000..815c58db --- /dev/null +++ b/patches/wined3d-CSMT_Main/0059-wined3d-Shadow-device-offscreenBuffer-in-the-context.patch @@ -0,0 +1,54 @@ +From e0c083d32b61b7a5bee9371bcf8a1b03964303a0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 4 Apr 2013 14:40:47 +0200 +Subject: wined3d: Shadow device->offscreenBuffer in the context + +Meh. Should probably go into the adapter, or non-fbo ORM should just die +TODO 2: See what this is actually used for. +--- + dlls/wined3d/context.c | 2 ++ + dlls/wined3d/device.c | 1 + + dlls/wined3d/wined3d_private.h | 2 ++ + 3 files changed, 5 insertions(+) + +diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c +index 7ba4086..fc66ff1 100644 +--- a/dlls/wined3d/context.c ++++ b/dlls/wined3d/context.c +@@ -1453,6 +1453,8 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain, + ret->current_fb.rt_size = gl_info->limits.buffers; + if (!ret->current_fb.render_targets) + goto out; ++ if (device->context_count) ++ ret->offscreenBuffer = device->contexts[0]->offscreenBuffer; + + /* Initialize the texture unit mapping to a 1:1 mapping */ + for (s = 0; s < MAX_COMBINED_SAMPLERS; ++s) +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index 98c0717..ee8b418 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -948,6 +948,7 @@ HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device, + } + } + } ++ device->contexts[0]->offscreenBuffer = device->offscreenBuffer; + + TRACE("All defaults now set up, leaving 3D init.\n"); + +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index ba0ce26..a16909c 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -1232,6 +1232,8 @@ struct wined3d_context + GLfloat fog_coord_value; + GLfloat color[4], fogstart, fogend, fogcolor[4]; + GLuint dummy_arbfp_prog; ++ ++ GLenum offscreenBuffer; + }; + + typedef void (*APPLYSTATEFUNC)(struct wined3d_context *ctx, const struct wined3d_state *state, DWORD state_id); +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0060-wined3d-Don-t-access-the-stateblock-in-find_draw_buf.patch b/patches/wined3d-CSMT_Main/0060-wined3d-Don-t-access-the-stateblock-in-find_draw_buf.patch new file mode 100644 index 00000000..50f64ee9 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0060-wined3d-Don-t-access-the-stateblock-in-find_draw_buf.patch @@ -0,0 +1,105 @@ +From 61077043981635623c0f2eda20aa252c18fc4104 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 4 Apr 2013 14:43:23 +0200 +Subject: wined3d: Don't access the stateblock in find_draw_buffers_mask + +--- + dlls/wined3d/context.c | 21 +++++++++------------ + 1 file changed, 9 insertions(+), 12 deletions(-) + +diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c +index fc66ff1..39c9464 100644 +--- a/dlls/wined3d/context.c ++++ b/dlls/wined3d/context.c +@@ -2231,14 +2231,14 @@ static void context_validate_onscreen_formats(struct wined3d_context *context, + context_set_render_offscreen(context, TRUE); + } + +-static DWORD context_generate_rt_mask_no_fbo(const struct wined3d_device *device, const struct wined3d_surface *rt) ++static DWORD context_generate_rt_mask_no_fbo(const struct wined3d_context *context, const struct wined3d_surface *rt) + { + if (!rt || rt->resource.format->id == WINED3DFMT_NULL) + return 0; + else if (rt->container->swapchain) + return context_generate_rt_mask_from_surface(rt); + else +- return context_generate_rt_mask(device->offscreenBuffer); ++ return context_generate_rt_mask(context->offscreenBuffer); + } + + /* Context activation is done by the caller. */ +@@ -2270,7 +2270,7 @@ void context_apply_blit_state(struct wined3d_context *context, const struct wine + } + else + { +- rt_mask = context_generate_rt_mask_no_fbo(device, rt); ++ rt_mask = context_generate_rt_mask_no_fbo(context, rt); + } + + cur_mask = context->current_fbo ? &context->current_fbo->rt_mask : &context->draw_buffers_mask; +@@ -2356,7 +2356,7 @@ BOOL context_apply_clear_state(struct wined3d_context *context, const struct win + } + else + { +- rt_mask = context_generate_rt_mask_no_fbo(device, ++ rt_mask = context_generate_rt_mask_no_fbo(context, + rt_count ? wined3d_rendertarget_view_get_surface(rts[0]) : NULL); + } + +@@ -2373,7 +2373,7 @@ BOOL context_apply_clear_state(struct wined3d_context *context, const struct win + } + else + { +- rt_mask = context_generate_rt_mask_no_fbo(device, ++ rt_mask = context_generate_rt_mask_no_fbo(context, + rt_count ? wined3d_rendertarget_view_get_surface(rts[0]) : NULL); + } + +@@ -2408,16 +2408,15 @@ BOOL context_apply_clear_state(struct wined3d_context *context, const struct win + return TRUE; + } + +-static DWORD find_draw_buffers_mask(const struct wined3d_context *context, const struct wined3d_device *device) ++static DWORD find_draw_buffers_mask(const struct wined3d_context *context, const struct wined3d_state *state) + { +- const struct wined3d_state *state = &device->state; + struct wined3d_rendertarget_view **rts = state->fb.render_targets; + struct wined3d_shader *ps = state->shader[WINED3D_SHADER_TYPE_PIXEL]; + DWORD rt_mask, rt_mask_bits; + unsigned int i; + + if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) +- return context_generate_rt_mask_no_fbo(device, wined3d_rendertarget_view_get_surface(rts[0])); ++ return context_generate_rt_mask_no_fbo(context, wined3d_rendertarget_view_get_surface(rts[0])); + else if (!context->render_offscreen) + return context_generate_rt_mask_from_surface(wined3d_rendertarget_view_get_surface(rts[0])); + +@@ -2440,9 +2439,8 @@ static DWORD find_draw_buffers_mask(const struct wined3d_context *context, const + /* Context activation is done by the caller. */ + void context_state_fb(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) + { +- const struct wined3d_device *device = context->swapchain->device; + const struct wined3d_fb_state *fb = &state->fb; +- DWORD rt_mask = find_draw_buffers_mask(context, device); ++ DWORD rt_mask = find_draw_buffers_mask(context, state); + DWORD *cur_mask; + + if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) +@@ -2710,13 +2708,12 @@ static void context_update_tex_unit_map(struct wined3d_context *context, const s + /* Context activation is done by the caller. */ + void context_state_drawbuf(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) + { +- const struct wined3d_device *device = context->swapchain->device; + DWORD rt_mask, *cur_mask; + + if (isStateDirty(context, STATE_FRAMEBUFFER)) return; + + cur_mask = context->current_fbo ? &context->current_fbo->rt_mask : &context->draw_buffers_mask; +- rt_mask = find_draw_buffers_mask(context, device); ++ rt_mask = find_draw_buffers_mask(context, state); + if (rt_mask != *cur_mask) + { + context_apply_draw_buffers(context, rt_mask); +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0061-wined3d-Pass-the-depth-stencil-to-swapchain-present.patch b/patches/wined3d-CSMT_Main/0061-wined3d-Pass-the-depth-stencil-to-swapchain-present.patch new file mode 100644 index 00000000..978da3e7 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0061-wined3d-Pass-the-depth-stencil-to-swapchain-present.patch @@ -0,0 +1,95 @@ +From 7b57d279336b852ad0286bdb865deeba2e55f3eb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 4 Apr 2013 14:52:24 +0200 +Subject: wined3d: Pass the depth stencil to swapchain->present + +TODO: Test if D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL discards the current +DS or the implicit DS. +--- + dlls/wined3d/cs.c | 3 ++- + dlls/wined3d/swapchain.c | 21 ++++++++++----------- + dlls/wined3d/wined3d_private.h | 3 ++- + 3 files changed, 14 insertions(+), 13 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 8b24e73..03e760d 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -429,7 +429,8 @@ static UINT wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data) + wined3d_swapchain_set_window(swapchain, op->dst_window_override); + + swapchain->swapchain_ops->swapchain_present(swapchain, +- src_rect, dst_rect, dirty_region, op->flags); ++ src_rect, dst_rect, dirty_region, op->flags, ++ wined3d_rendertarget_view_get_surface(cs->state.fb.depth_stencil)); + + return sizeof(*op); + } +diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c +index 60504ef..e190892 100644 +--- a/dlls/wined3d/swapchain.c ++++ b/dlls/wined3d/swapchain.c +@@ -417,11 +417,11 @@ static void swapchain_blit(const struct wined3d_swapchain *swapchain, + } + + static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT *src_rect_in, +- const RECT *dst_rect_in, const RGNDATA *dirty_region, DWORD flags) ++ 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)); +- const struct wined3d_fb_state *fb = &swapchain->device->state.fb; + const struct wined3d_gl_info *gl_info; + struct wined3d_context *context; + struct wined3d_surface *front; +@@ -574,16 +574,14 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT + break; + } + +- if (fb->depth_stencil) ++ if (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)) ++ if (swapchain->desc.flags & WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL ++ || depth_stencil->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) ++ surface_modify_ds_location(depth_stencil, WINED3D_LOCATION_DISCARDED, ++ depth_stencil->resource.width, depth_stencil->resource.height); ++ if (depth_stencil == swapchain->device->onscreen_depth_stencil) + { + wined3d_surface_decref(swapchain->device->onscreen_depth_stencil); + swapchain->device->onscreen_depth_stencil = NULL; +@@ -647,7 +645,8 @@ void x11_copy_to_screen(const struct wined3d_swapchain *swapchain, const RECT *r + } + + static void swapchain_gdi_present(struct wined3d_swapchain *swapchain, const RECT *src_rect_in, +- const RECT *dst_rect_in, const RGNDATA *dirty_region, DWORD flags) ++ const RECT *dst_rect_in, const RGNDATA *dirty_region, DWORD flags, ++ struct wined3d_surface *depth_stencil) + { + struct wined3d_surface *front, *back; + +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index a16909c..024b55b 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2746,7 +2746,8 @@ struct wined3d_shader_resource_view + struct wined3d_swapchain_ops + { + void (*swapchain_present)(struct wined3d_swapchain *swapchain, const RECT *src_rect, +- const RECT *dst_rect, const RGNDATA *dirty_region, DWORD flags); ++ const RECT *dst_rect, const RGNDATA *dirty_region, DWORD flags, ++ struct wined3d_surface *depth_stencil); + }; + + struct wined3d_swapchain +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0062-wined3d-Don-t-store-viewport-pointers-in-the-command.patch b/patches/wined3d-CSMT_Main/0062-wined3d-Don-t-store-viewport-pointers-in-the-command.patch new file mode 100644 index 00000000..207f5ebc --- /dev/null +++ b/patches/wined3d-CSMT_Main/0062-wined3d-Don-t-store-viewport-pointers-in-the-command.patch @@ -0,0 +1,47 @@ +From eb236d88cef3c5c73289c1147466a1cc85657500 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Fri, 5 Apr 2013 10:12:06 +0200 +Subject: wined3d: Don't store viewport pointers in the command stream. + +--- + dlls/wined3d/cs.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 03e760d..4b1ed18 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -126,7 +126,7 @@ struct wined3d_cs_set_predication + struct wined3d_cs_set_viewport + { + enum wined3d_cs_op opcode; +- const struct wined3d_viewport *viewport; ++ struct wined3d_viewport viewport; + }; + + struct wined3d_cs_set_scissor_rect +@@ -552,9 +552,10 @@ void wined3d_cs_emit_set_predication(struct wined3d_cs *cs, struct wined3d_query + static UINT wined3d_cs_exec_set_viewport(struct wined3d_cs *cs, const void *data) + { + const struct wined3d_cs_set_viewport *op = data; ++ struct wined3d_device *device = cs->device; + +- cs->state.viewport = *op->viewport; +- device_invalidate_state(cs->device, STATE_VIEWPORT); ++ cs->state.viewport = op->viewport; ++ device_invalidate_state(device, STATE_VIEWPORT); + + return sizeof(*op); + } +@@ -565,7 +566,7 @@ void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_vi + + op = cs->ops->require_space(cs, sizeof(*op)); + op->opcode = WINED3D_CS_OP_SET_VIEWPORT; +- op->viewport = viewport; ++ op->viewport = *viewport; + + cs->ops->submit(cs); + } +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0063-wined3d-Keep-track-of-the-onscreen-depth-stencil-in-.patch b/patches/wined3d-CSMT_Main/0063-wined3d-Keep-track-of-the-onscreen-depth-stencil-in-.patch new file mode 100644 index 00000000..2fcf8fb5 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0063-wined3d-Keep-track-of-the-onscreen-depth-stencil-in-.patch @@ -0,0 +1,216 @@ +From 9afc54cc004880662dff5ebe6734d27b11c2e8bc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Fri, 5 Apr 2013 14:37:44 +0200 +Subject: wined3d: Keep track of the onscreen depth stencil in the command + stream instead of the device. + +Based on a patch by Henri Verbeet. + +TODO: Not sure if its the right way to go. There are certainly some +missing bits, e.g. accessing the cs via the device in all but one places +defeats the point of this at the moment. + +Since the GL onscreen depth stencil is part of the WGL framebuffer, +which belongs to the swapchain, storing this info in the swapchain might +be the right thing to do. This should help multi-window or multi-head +configurations. +--- + dlls/wined3d/cs.c | 22 +++++++++++++++++++--- + dlls/wined3d/device.c | 35 ++++++++++------------------------- + dlls/wined3d/drawprim.c | 4 ++-- + dlls/wined3d/swapchain.c | 6 +++--- + dlls/wined3d/wined3d_private.h | 10 ++++------ + 5 files changed, 38 insertions(+), 39 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 4b1ed18..236e2f2 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -629,10 +629,10 @@ static UINT wined3d_cs_exec_set_depth_stencil_view(struct wined3d_cs *cs, const + || 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) ++ if (prev_surface == cs->onscreen_depth_stencil) + { +- wined3d_surface_decref(device->onscreen_depth_stencil); +- device->onscreen_depth_stencil = NULL; ++ wined3d_surface_decref(cs->onscreen_depth_stencil); ++ cs->onscreen_depth_stencil = NULL; + } + } + } +@@ -1365,6 +1365,22 @@ static void wined3d_cs_emit_stop(struct wined3d_cs *cs) + wined3d_cs_flush(cs); + } + ++void wined3d_cs_switch_onscreen_ds(struct wined3d_cs *cs, ++ struct wined3d_context *context, struct wined3d_surface *depth_stencil) ++{ ++ if (cs->onscreen_depth_stencil) ++ { ++ surface_load_ds_location(cs->onscreen_depth_stencil, context, WINED3D_LOCATION_TEXTURE_RGB); ++ ++ surface_modify_ds_location(cs->onscreen_depth_stencil, WINED3D_LOCATION_TEXTURE_RGB, ++ cs->onscreen_depth_stencil->ds_current_size.cx, ++ cs->onscreen_depth_stencil->ds_current_size.cy); ++ wined3d_surface_decref(cs->onscreen_depth_stencil); ++ } ++ cs->onscreen_depth_stencil = depth_stencil; ++ wined3d_surface_incref(cs->onscreen_depth_stencil); ++} ++ + static DWORD WINAPI wined3d_cs_run(void *thread_param) + { + struct wined3d_cs *cs = thread_param; +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index ee8b418..dfc0619 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -198,22 +198,6 @@ void device_context_remove(struct wined3d_device *device, struct wined3d_context + device->contexts = new_array; + } + +-void device_switch_onscreen_ds(struct wined3d_device *device, +- struct wined3d_context *context, struct wined3d_surface *depth_stencil) +-{ +- if (device->onscreen_depth_stencil) +- { +- surface_load_ds_location(device->onscreen_depth_stencil, context, WINED3D_LOCATION_TEXTURE_RGB); +- +- surface_modify_ds_location(device->onscreen_depth_stencil, WINED3D_LOCATION_TEXTURE_RGB, +- device->onscreen_depth_stencil->ds_current_size.cx, +- device->onscreen_depth_stencil->ds_current_size.cy); +- wined3d_surface_decref(device->onscreen_depth_stencil); +- } +- device->onscreen_depth_stencil = depth_stencil; +- wined3d_surface_incref(device->onscreen_depth_stencil); +-} +- + static BOOL is_full_clear(const struct wined3d_surface *target, const RECT *draw_rect, const RECT *clear_rect) + { + /* partial draw rect */ +@@ -343,8 +327,8 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c + { + DWORD location = render_offscreen ? fb->depth_stencil->resource->draw_binding : WINED3D_LOCATION_DRAWABLE; + +- if (!render_offscreen && depth_stencil != device->onscreen_depth_stencil) +- device_switch_onscreen_ds(device, context, depth_stencil); ++ if (!render_offscreen && depth_stencil != device->cs->onscreen_depth_stencil) ++ wined3d_cs_switch_onscreen_ds(device->cs, context, depth_stencil); + prepare_ds_clear(depth_stencil, context, location, + draw_rect, rect_count, clear_rect, &ds_rect); + } +@@ -1043,11 +1027,12 @@ HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device) + /* Release the buffers (with sanity checks). + * FIXME: Move this move into a separate patch. I think the idea + * behind this is that those surfaces should be freed before unloading +- * remaining resources below. */ +- if (device->onscreen_depth_stencil) ++ * remaining resources below. ++ * FIXME 2: Shouldn't the cs take care of onscreen_depth_stencil? */ ++ if (device->cs->onscreen_depth_stencil) + { +- surface = device->onscreen_depth_stencil; +- device->onscreen_depth_stencil = NULL; ++ surface = device->cs->onscreen_depth_stencil; ++ device->cs->onscreen_depth_stencil = NULL; + wined3d_surface_decref(surface); + } + +@@ -4400,10 +4385,10 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device, + state_unbind_resources(&device->state); + } + +- if (device->onscreen_depth_stencil) ++ if (device->cs->onscreen_depth_stencil) + { +- wined3d_surface_decref(device->onscreen_depth_stencil); +- device->onscreen_depth_stencil = NULL; ++ wined3d_surface_decref(device->cs->onscreen_depth_stencil); ++ device->cs->onscreen_depth_stencil = NULL; + } + + if (reset_state) +diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c +index 43d867d..5eb80f0 100644 +--- a/dlls/wined3d/drawprim.c ++++ b/dlls/wined3d/drawprim.c +@@ -644,8 +644,8 @@ void draw_primitive(struct wined3d_device *device, const struct wined3d_state *s + struct wined3d_surface *ds = wined3d_rendertarget_view_get_surface(state->fb.depth_stencil); + RECT current_rect, draw_rect, r; + +- if (!context->render_offscreen && ds != device->onscreen_depth_stencil) +- device_switch_onscreen_ds(device, context, ds); ++ if (!context->render_offscreen && ds != device->cs->onscreen_depth_stencil) ++ wined3d_cs_switch_onscreen_ds(device->cs, context, ds); + + if (ds->resource.locations & location) + SetRect(¤t_rect, 0, 0, ds->ds_current_size.cx, ds->ds_current_size.cy); +diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c +index e190892..fa0c241 100644 +--- a/dlls/wined3d/swapchain.c ++++ b/dlls/wined3d/swapchain.c +@@ -581,10 +581,10 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT + { + surface_modify_ds_location(depth_stencil, WINED3D_LOCATION_DISCARDED, + depth_stencil->resource.width, depth_stencil->resource.height); +- if (depth_stencil == swapchain->device->onscreen_depth_stencil) ++ if (depth_stencil == swapchain->device->cs->onscreen_depth_stencil) + { +- wined3d_surface_decref(swapchain->device->onscreen_depth_stencil); +- swapchain->device->onscreen_depth_stencil = NULL; ++ wined3d_surface_decref(swapchain->device->cs->onscreen_depth_stencil); ++ swapchain->device->cs->onscreen_depth_stencil = NULL; + } + } + } +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 024b55b..e4dbd9d 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2011,14 +2011,11 @@ struct wined3d_device + struct wined3d_rendertarget_view *back_buffer_view; + struct wined3d_swapchain **swapchains; + UINT swapchain_count; ++ 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) */ + +- /* Render Target Support */ +- struct wined3d_surface *onscreen_depth_stencil; +- struct wined3d_rendertarget_view *auto_depth_stencil_view; +- + /* For rendering to a texture using glCopyTexImage */ + GLuint depth_blt_texture; + +@@ -2060,8 +2057,6 @@ LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL + 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; +-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; + + static inline BOOL isStateDirty(const struct wined3d_context *context, DWORD state) +@@ -2556,6 +2551,7 @@ struct wined3d_cs + struct wined3d_state state; + HANDLE thread; + DWORD tls_idx; ++ struct wined3d_surface *onscreen_depth_stencil; + + size_t data_size; + void *data; +@@ -2566,6 +2562,8 @@ struct wined3d_cs + + struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device) DECLSPEC_HIDDEN; + 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; + + 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; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0064-wined3d-Send-base-vertex-index-updates-through-the-c.patch b/patches/wined3d-CSMT_Main/0064-wined3d-Send-base-vertex-index-updates-through-the-c.patch new file mode 100644 index 00000000..a9c7bc3b --- /dev/null +++ b/patches/wined3d-CSMT_Main/0064-wined3d-Send-base-vertex-index-updates-through-the-c.patch @@ -0,0 +1,178 @@ +From 4b5e47ede0b1ac538b6439e8b1888e4da542ceee Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Sun, 7 Apr 2013 17:33:20 +0200 +Subject: wined3d: Send base vertex index updates through the cs + +--- + dlls/wined3d/cs.c | 49 ++++++++++++++++++++++++++++++++++++++---- + dlls/wined3d/device.c | 17 +++------------ + dlls/wined3d/wined3d_private.h | 2 ++ + 3 files changed, 50 insertions(+), 18 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 236e2f2..0525a59 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -66,6 +66,7 @@ enum wined3d_cs_op + WINED3D_CS_OP_SET_VS_CONSTS_F, + WINED3D_CS_OP_SET_PS_CONSTS_F, + WINED3D_CS_OP_GLFINISH, ++ WINED3D_CS_OP_SET_BASE_VERTEX_INDEX, + WINED3D_CS_OP_STOP, + }; + +@@ -290,6 +291,12 @@ struct wined3d_cs_finish + enum wined3d_cs_op opcode; + }; + ++struct wined3d_cs_set_base_vertex_index ++{ ++ enum wined3d_cs_op opcode; ++ UINT base_vertex_index; ++}; ++ + /* FIXME: The list synchronization probably isn't particularly fast. */ + static void wined3d_cs_list_enqueue(struct wined3d_cs_list *list, struct wined3d_cs_block *block) + { +@@ -504,6 +511,21 @@ void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT * + static UINT wined3d_cs_exec_draw(struct wined3d_cs *cs, const void *data) + { + const struct wined3d_cs_draw *op = data; ++ const struct wined3d_gl_info *gl_info = &cs->device->adapter->gl_info; ++ ++ if (op->indexed && !gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX]) ++ { ++ if (cs->state.load_base_vertex_index != cs->state.base_vertex_index) ++ { ++ cs->state.load_base_vertex_index = cs->state.base_vertex_index; ++ device_invalidate_state(cs->device, STATE_BASEVERTEXINDEX); ++ } ++ } ++ else if (cs->state.load_base_vertex_index) ++ { ++ cs->state.load_base_vertex_index = 0; ++ device_invalidate_state(cs->device, STATE_BASEVERTEXINDEX); ++ } + + draw_primitive(cs->device, &cs->state, op->start_idx, op->index_count, + op->start_instance, op->instance_count, op->indexed); +@@ -931,8 +953,6 @@ static UINT wined3d_cs_exec_transfer_stateblock(struct wined3d_cs *cs, const voi + /* Don't memcpy the entire struct, we'll remove single items as we add dedicated + * ops for setting states */ + +- cs->state.base_vertex_index = op->state.base_vertex_index; +- cs->state.load_base_vertex_index = op->state.load_base_vertex_index; + cs->state.gl_primitive_type = op->state.gl_primitive_type; + + memcpy(cs->state.vs_consts_b, op->state.vs_consts_b, sizeof(cs->state.vs_consts_b)); +@@ -955,8 +975,6 @@ void wined3d_cs_emit_transfer_stateblock(struct wined3d_cs *cs, const struct win + + /* Don't memcpy the entire struct, we'll remove single items as we add dedicated + * ops for setting states */ +- op->state.base_vertex_index = state->base_vertex_index; +- op->state.load_base_vertex_index = state->load_base_vertex_index; + op->state.gl_primitive_type = state->gl_primitive_type; + + memcpy(op->state.vs_consts_b, state->vs_consts_b, sizeof(op->state.vs_consts_b)); +@@ -1281,6 +1299,28 @@ void wined3d_cs_emit_glfinish(struct wined3d_cs *cs) + cs->ops->submit(cs); + } + ++static UINT wined3d_cs_exec_set_base_vertex_index(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_set_base_vertex_index *op = data; ++ ++ cs->state.base_vertex_index = op->base_vertex_index; ++ device_invalidate_state(cs->device, STATE_BASEVERTEXINDEX); ++ ++ return sizeof(*op); ++} ++ ++void wined3d_cs_emit_set_base_vertex_index(struct wined3d_cs *cs, ++ UINT base_vertex_index) ++{ ++ struct wined3d_cs_set_base_vertex_index *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_SET_BASE_VERTEX_INDEX; ++ op->base_vertex_index = base_vertex_index; ++ ++ cs->ops->submit(cs); ++} ++ + static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = + { + /* WINED3D_CS_OP_FENCE */ wined3d_cs_exec_fence, +@@ -1313,6 +1353,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* WINED3D_CS_OP_SET_VS_CONSTS_F */ wined3d_cs_exec_set_vs_consts_f, + /* WINED3D_CS_OP_SET_PS_CONSTS_F */ wined3d_cs_exec_set_ps_consts_f, + /* WINED3D_CS_OP_GLFINISH */ wined3d_cs_exec_glfinish, ++ /* WINED3D_CS_OP_SET_BASE_VERTEX_INDEX */ wined3d_cs_exec_set_base_vertex_index, + }; + + static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size) +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index dfc0619..a80784b 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -1830,6 +1830,9 @@ void CDECL wined3d_device_set_base_vertex_index(struct wined3d_device *device, I + TRACE("device %p, base_index %d.\n", device, base_index); + + device->update_state->base_vertex_index = base_index; ++ ++ if (!device->recording) ++ wined3d_cs_emit_set_base_vertex_index(device->cs, base_index); + } + + INT CDECL wined3d_device_get_base_vertex_index(const struct wined3d_device *device) +@@ -3377,12 +3380,6 @@ HRESULT CDECL wined3d_device_draw_primitive(struct wined3d_device *device, UINT + return WINED3DERR_INVALIDCALL; + } + +- if (device->state.load_base_vertex_index) +- { +- device->state.load_base_vertex_index = 0; +- device_invalidate_state(device, STATE_BASEVERTEXINDEX); +- } +- + wined3d_cs_emit_transfer_stateblock(device->cs, &device->state); + wined3d_cs_emit_draw(device->cs, start_vertex, vertex_count, 0, 0, FALSE); + +@@ -3391,8 +3388,6 @@ HRESULT CDECL wined3d_device_draw_primitive(struct wined3d_device *device, UINT + + HRESULT CDECL wined3d_device_draw_indexed_primitive(struct wined3d_device *device, UINT start_idx, UINT index_count) + { +- const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; +- + TRACE("device %p, start_idx %u, index_count %u.\n", device, start_idx, index_count); + + if (!device->state.index_buffer) +@@ -3411,12 +3406,6 @@ HRESULT CDECL wined3d_device_draw_indexed_primitive(struct wined3d_device *devic + return WINED3DERR_INVALIDCALL; + } + +- if (!gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX] && +- device->state.load_base_vertex_index != device->state.base_vertex_index) +- { +- device->state.load_base_vertex_index = device->state.base_vertex_index; +- device_invalidate_state(device, STATE_BASEVERTEXINDEX); +- } + + wined3d_cs_emit_transfer_stateblock(device->cs, &device->state); + wined3d_cs_emit_draw(device->cs, start_idx, index_count, 0, 0, TRUE); +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index e4dbd9d..382c120 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2616,6 +2616,8 @@ void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_vi + 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_glfinish(struct wined3d_cs *cs) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_set_base_vertex_index(struct wined3d_cs *cs, ++ UINT base_vertex_index) DECLSPEC_HIDDEN; + + /* 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 +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0065-wined3d-Send-primitive-type-updates-through-the-comm.patch b/patches/wined3d-CSMT_Main/0065-wined3d-Send-primitive-type-updates-through-the-comm.patch new file mode 100644 index 00000000..682c34e1 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0065-wined3d-Send-primitive-type-updates-through-the-comm.patch @@ -0,0 +1,151 @@ +From a322b70c446dcd49facd2c6987a70b289c4678d1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Sun, 7 Apr 2013 17:53:43 +0200 +Subject: wined3d: Send primitive type updates through the command stream + +--- + dlls/wined3d/cs.c | 39 ++++++++++++++++++++++++++++++++++----- + dlls/wined3d/device.c | 5 ++--- + dlls/wined3d/stateblock.c | 4 ++-- + dlls/wined3d/wined3d_private.h | 2 ++ + 4 files changed, 40 insertions(+), 10 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 0525a59..a7ba2b4 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -67,6 +67,7 @@ enum wined3d_cs_op + WINED3D_CS_OP_SET_PS_CONSTS_F, + WINED3D_CS_OP_GLFINISH, + WINED3D_CS_OP_SET_BASE_VERTEX_INDEX, ++ WINED3D_CS_OP_SET_PRIMITIVE_TYPE, + WINED3D_CS_OP_STOP, + }; + +@@ -297,6 +298,12 @@ struct wined3d_cs_set_base_vertex_index + UINT base_vertex_index; + }; + ++struct wined3d_cs_set_primitive_type ++{ ++ enum wined3d_cs_op opcode; ++ GLenum gl_primitive_type; ++}; ++ + /* FIXME: The list synchronization probably isn't particularly fast. */ + static void wined3d_cs_list_enqueue(struct wined3d_cs_list *list, struct wined3d_cs_block *block) + { +@@ -952,9 +959,6 @@ static UINT wined3d_cs_exec_transfer_stateblock(struct wined3d_cs *cs, const voi + + /* Don't memcpy the entire struct, we'll remove single items as we add dedicated + * ops for setting states */ +- +- cs->state.gl_primitive_type = op->state.gl_primitive_type; +- + memcpy(cs->state.vs_consts_b, op->state.vs_consts_b, sizeof(cs->state.vs_consts_b)); + memcpy(cs->state.vs_consts_i, op->state.vs_consts_i, sizeof(cs->state.vs_consts_i)); + +@@ -975,8 +979,6 @@ void wined3d_cs_emit_transfer_stateblock(struct wined3d_cs *cs, const struct win + + /* Don't memcpy the entire struct, we'll remove single items as we add dedicated + * ops for setting states */ +- op->state.gl_primitive_type = state->gl_primitive_type; +- + memcpy(op->state.vs_consts_b, state->vs_consts_b, sizeof(op->state.vs_consts_b)); + memcpy(op->state.vs_consts_i, state->vs_consts_i, sizeof(op->state.vs_consts_i)); + +@@ -1321,6 +1323,32 @@ void wined3d_cs_emit_set_base_vertex_index(struct wined3d_cs *cs, + cs->ops->submit(cs); + } + ++static UINT wined3d_cs_exec_set_primitive_type(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_set_primitive_type *op = data; ++ GLenum prev; ++ ++ prev = cs->state.gl_primitive_type; ++ ++ if (op->gl_primitive_type == GL_POINTS || prev == GL_POINTS) ++ device_invalidate_state(cs->device, STATE_POINT_SIZE_ENABLE); ++ ++ cs->state.gl_primitive_type = op->gl_primitive_type; ++ ++ return sizeof(*op); ++} ++ ++void wined3d_cs_emit_set_primitive_type(struct wined3d_cs *cs, GLenum primitive_type) ++{ ++ struct wined3d_cs_set_primitive_type *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_SET_PRIMITIVE_TYPE; ++ op->gl_primitive_type = primitive_type; ++ ++ cs->ops->submit(cs); ++} ++ + static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = + { + /* WINED3D_CS_OP_FENCE */ wined3d_cs_exec_fence, +@@ -1354,6 +1382,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* WINED3D_CS_OP_SET_PS_CONSTS_F */ wined3d_cs_exec_set_ps_consts_f, + /* 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, + }; + + static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size) +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index a80784b..e87a52c 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -3348,7 +3348,6 @@ void CDECL wined3d_device_set_primitive_type(struct wined3d_device *device, + enum wined3d_primitive_type primitive_type) + { + GLenum gl_primitive_type, prev; +- + TRACE("device %p, primitive_type %s\n", device, debug_d3dprimitivetype(primitive_type)); + + gl_primitive_type = gl_primitive_type_from_d3d(primitive_type); +@@ -3356,8 +3355,8 @@ void CDECL wined3d_device_set_primitive_type(struct wined3d_device *device, + device->update_state->gl_primitive_type = gl_primitive_type; + if (device->recording) + device->recording->changed.primitive_type = TRUE; +- else if (gl_primitive_type != prev && (gl_primitive_type == GL_POINTS || prev == GL_POINTS)) +- device_invalidate_state(device, STATE_POINT_SIZE_ENABLE); ++ else if (gl_primitive_type != prev) ++ wined3d_cs_emit_set_primitive_type(device->cs, gl_primitive_type); + } + + void CDECL wined3d_device_get_primitive_type(const struct wined3d_device *device, +diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c +index 141e539..606134c 100644 +--- a/dlls/wined3d/stateblock.c ++++ b/dlls/wined3d/stateblock.c +@@ -1075,8 +1075,8 @@ void CDECL wined3d_stateblock_apply(const struct wined3d_stateblock *stateblock) + 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 (gl_primitive_type != prev && (gl_primitive_type == GL_POINTS || prev == GL_POINTS)) +- device_invalidate_state(device, STATE_POINT_SIZE_ENABLE); ++ if (gl_primitive_type != prev) ++ wined3d_cs_emit_set_primitive_type(device->cs, gl_primitive_type); + } + + if (stateblock->changed.indices) +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 382c120..a647ca9 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2618,6 +2618,8 @@ void wined3d_cs_emit_set_consts_f(struct wined3d_cs *cs, UINT start_register, co + void wined3d_cs_emit_glfinish(struct wined3d_cs *cs) DECLSPEC_HIDDEN; + void wined3d_cs_emit_set_base_vertex_index(struct wined3d_cs *cs, + UINT base_vertex_index) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_set_primitive_type(struct wined3d_cs *cs, ++ GLenum primitive_type) DECLSPEC_HIDDEN; + + /* 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 +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0066-wined3d-Send-bool-constant-updates-through-the-comma.patch b/patches/wined3d-CSMT_Main/0066-wined3d-Send-bool-constant-updates-through-the-comma.patch new file mode 100644 index 00000000..63cd8b2f --- /dev/null +++ b/patches/wined3d-CSMT_Main/0066-wined3d-Send-bool-constant-updates-through-the-comma.patch @@ -0,0 +1,192 @@ +From 870ae689d58feb0e2c28603ab7a5c202dc1bf6c2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Tue, 9 Apr 2013 21:50:30 +0200 +Subject: wined3d: Send bool constant updates through the command stream + +--- + dlls/wined3d/cs.c | 72 +++++++++++++++++++++++++++++++++++++++--- + dlls/wined3d/device.c | 8 +++-- + dlls/wined3d/wined3d_private.h | 3 ++ + 3 files changed, 76 insertions(+), 7 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index a7ba2b4..9d8491a 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -64,7 +64,9 @@ enum wined3d_cs_op + WINED3D_CS_OP_RESET_STATE, + WINED3D_CS_OP_STATEBLOCK, + WINED3D_CS_OP_SET_VS_CONSTS_F, ++ WINED3D_CS_OP_SET_VS_CONSTS_B, + WINED3D_CS_OP_SET_PS_CONSTS_F, ++ WINED3D_CS_OP_SET_PS_CONSTS_B, + WINED3D_CS_OP_GLFINISH, + WINED3D_CS_OP_SET_BASE_VERTEX_INDEX, + WINED3D_CS_OP_SET_PRIMITIVE_TYPE, +@@ -287,6 +289,13 @@ struct wined3d_cs_set_consts_f + float constants[4]; + }; + ++struct wined3d_cs_set_consts_b ++{ ++ enum wined3d_cs_op opcode; ++ UINT start_register, bool_count; ++ BOOL constants[1]; ++}; ++ + struct wined3d_cs_finish + { + enum wined3d_cs_op opcode; +@@ -959,10 +968,8 @@ static UINT wined3d_cs_exec_transfer_stateblock(struct wined3d_cs *cs, const voi + + /* Don't memcpy the entire struct, we'll remove single items as we add dedicated + * ops for setting states */ +- memcpy(cs->state.vs_consts_b, op->state.vs_consts_b, sizeof(cs->state.vs_consts_b)); + memcpy(cs->state.vs_consts_i, op->state.vs_consts_i, sizeof(cs->state.vs_consts_i)); + +- memcpy(cs->state.ps_consts_b, op->state.ps_consts_b, sizeof(cs->state.ps_consts_b)); + memcpy(cs->state.ps_consts_i, op->state.ps_consts_i, sizeof(cs->state.ps_consts_i)); + + memcpy(cs->state.lights, op->state.lights, sizeof(cs->state.lights)); +@@ -979,10 +986,8 @@ void wined3d_cs_emit_transfer_stateblock(struct wined3d_cs *cs, const struct win + + /* Don't memcpy the entire struct, we'll remove single items as we add dedicated + * ops for setting states */ +- memcpy(op->state.vs_consts_b, state->vs_consts_b, sizeof(op->state.vs_consts_b)); + memcpy(op->state.vs_consts_i, state->vs_consts_i, sizeof(op->state.vs_consts_i)); + +- memcpy(op->state.ps_consts_b, state->ps_consts_b, sizeof(op->state.ps_consts_b)); + memcpy(op->state.ps_consts_i, state->ps_consts_i, sizeof(op->state.ps_consts_i)); + + /* FIXME: This is not ideal. CS is still running synchronously, so this is ok. +@@ -1137,6 +1142,63 @@ void wined3d_cs_emit_set_render_state(struct wined3d_cs *cs, enum wined3d_render + op->value = value; + + cs->ops->submit(cs); ++}; ++ ++static UINT wined3d_cs_exec_set_vs_consts_b(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_set_consts_b *op = data; ++ struct wined3d_device *device = cs->device; ++ ++ memcpy(&cs->state.vs_consts_b[op->start_register], op->constants, ++ sizeof(*cs->state.vs_consts_b) * op->bool_count); ++ ++ device_invalidate_shader_constants(device, WINED3D_SHADER_CONST_VS_B); ++ ++ return sizeof(*op) + sizeof(op->constants) * (op->bool_count - 1); ++} ++ ++static UINT wined3d_cs_exec_set_ps_consts_b(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_set_consts_b *op = data; ++ struct wined3d_device *device = cs->device; ++ ++ memcpy(&cs->state.ps_consts_b[op->start_register], op->constants, ++ sizeof(*cs->state.ps_consts_b) * op->bool_count); ++ ++ device_invalidate_shader_constants(device, WINED3D_SHADER_CONST_PS_B); ++ ++ return sizeof(*op) + sizeof(op->constants) * (op->bool_count - 1); ++} ++ ++void wined3d_cs_emit_set_consts_b(struct wined3d_cs *cs, UINT start_register, ++ const BOOL *constants, UINT bool_count, enum wined3d_shader_type type) ++{ ++ struct wined3d_cs_set_consts_b *op; ++ UINT extra_space = bool_count - 1; ++ ++ op = cs->ops->require_space(cs, sizeof(*op) + sizeof(op->constants) * extra_space); ++ switch (type) ++ { ++ case WINED3D_SHADER_TYPE_PIXEL: ++ op->opcode = WINED3D_CS_OP_SET_PS_CONSTS_B; ++ break; ++ ++ case WINED3D_SHADER_TYPE_VERTEX: ++ op->opcode = WINED3D_CS_OP_SET_VS_CONSTS_B; ++ break; ++ ++ case WINED3D_SHADER_TYPE_GEOMETRY: ++ FIXME("Invalid for geometry shaders\n"); ++ return; ++ ++ case WINED3D_SHADER_TYPE_COUNT: ++ break; ++ } ++ op->start_register = start_register; ++ op->bool_count = bool_count; ++ memcpy(op->constants, constants, sizeof(op->constants) * bool_count); ++ ++ cs->ops->submit(cs); + } + + static UINT wined3d_cs_exec_set_texture_state(struct wined3d_cs *cs, const void *data) +@@ -1379,7 +1441,9 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* WINED3D_CS_OP_RESET_STATE */ wined3d_cs_exec_reset_state, + /* WINED3D_CS_OP_STATEBLOCK */ wined3d_cs_exec_transfer_stateblock, + /* 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_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_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, +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index e87a52c..14d3080 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -2197,7 +2197,7 @@ struct wined3d_sampler * CDECL wined3d_device_get_vs_sampler(const struct wined3 + return device->state.sampler[WINED3D_SHADER_TYPE_VERTEX][idx]; + } + +-static void device_invalidate_shader_constants(const struct wined3d_device *device, DWORD mask) ++void device_invalidate_shader_constants(const struct wined3d_device *device, DWORD mask) + { + UINT i; + +@@ -2230,7 +2230,8 @@ HRESULT CDECL wined3d_device_set_vs_consts_b(struct wined3d_device *device, + } + else + { +- device_invalidate_shader_constants(device, WINED3D_SHADER_CONST_VS_B); ++ wined3d_cs_emit_set_consts_b(device->cs, start_register, constants, ++ bool_count, WINED3D_SHADER_TYPE_VERTEX); + } + + return WINED3D_OK; +@@ -2464,7 +2465,8 @@ HRESULT CDECL wined3d_device_set_ps_consts_b(struct wined3d_device *device, + } + else + { +- device_invalidate_shader_constants(device, WINED3D_SHADER_CONST_PS_B); ++ wined3d_cs_emit_set_consts_b(device->cs, start_register, constants, ++ bool_count, WINED3D_SHADER_TYPE_PIXEL); + } + + return WINED3D_OK; +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index a647ca9..4ecb626 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2058,6 +2058,7 @@ LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL + 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; + 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; + + static inline BOOL isStateDirty(const struct wined3d_context *context, DWORD state) + { +@@ -2615,6 +2616,8 @@ void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs, + void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport *viewport) DECLSPEC_HIDDEN; + 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, ++ const BOOL *constants, UINT bool_count, enum wined3d_shader_type type) DECLSPEC_HIDDEN; + void wined3d_cs_emit_glfinish(struct wined3d_cs *cs) DECLSPEC_HIDDEN; + void wined3d_cs_emit_set_base_vertex_index(struct wined3d_cs *cs, + UINT base_vertex_index) DECLSPEC_HIDDEN; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0067-wined3d-Send-int-constant-updates-through-the-comman.patch b/patches/wined3d-CSMT_Main/0067-wined3d-Send-int-constant-updates-through-the-comman.patch new file mode 100644 index 00000000..61234603 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0067-wined3d-Send-int-constant-updates-through-the-comman.patch @@ -0,0 +1,175 @@ +From 68141ab2e84252e99bcf6801a5bcc629b1494665 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Wed, 10 Apr 2013 14:20:47 +0200 +Subject: wined3d: Send int constant updates through the command stream + +--- + dlls/wined3d/cs.c | 74 ++++++++++++++++++++++++++++++++++++++---- + dlls/wined3d/device.c | 6 ++-- + dlls/wined3d/wined3d_private.h | 2 ++ + 3 files changed, 74 insertions(+), 8 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 9d8491a..cf3a523 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -65,8 +65,10 @@ enum wined3d_cs_op + WINED3D_CS_OP_STATEBLOCK, + WINED3D_CS_OP_SET_VS_CONSTS_F, + WINED3D_CS_OP_SET_VS_CONSTS_B, ++ WINED3D_CS_OP_SET_VS_CONSTS_I, + WINED3D_CS_OP_SET_PS_CONSTS_F, + WINED3D_CS_OP_SET_PS_CONSTS_B, ++ WINED3D_CS_OP_SET_PS_CONSTS_I, + WINED3D_CS_OP_GLFINISH, + WINED3D_CS_OP_SET_BASE_VERTEX_INDEX, + WINED3D_CS_OP_SET_PRIMITIVE_TYPE, +@@ -296,6 +298,13 @@ struct wined3d_cs_set_consts_b + BOOL constants[1]; + }; + ++struct wined3d_cs_set_consts_i ++{ ++ enum wined3d_cs_op opcode; ++ UINT start_register, vector4i_count; ++ int constants[4]; ++}; ++ + struct wined3d_cs_finish + { + enum wined3d_cs_op opcode; +@@ -968,9 +977,6 @@ static UINT wined3d_cs_exec_transfer_stateblock(struct wined3d_cs *cs, const voi + + /* Don't memcpy the entire struct, we'll remove single items as we add dedicated + * ops for setting states */ +- memcpy(cs->state.vs_consts_i, op->state.vs_consts_i, sizeof(cs->state.vs_consts_i)); +- +- memcpy(cs->state.ps_consts_i, op->state.ps_consts_i, sizeof(cs->state.ps_consts_i)); + + memcpy(cs->state.lights, op->state.lights, sizeof(cs->state.lights)); + +@@ -986,9 +992,6 @@ void wined3d_cs_emit_transfer_stateblock(struct wined3d_cs *cs, const struct win + + /* Don't memcpy the entire struct, we'll remove single items as we add dedicated + * ops for setting states */ +- memcpy(op->state.vs_consts_i, state->vs_consts_i, sizeof(op->state.vs_consts_i)); +- +- memcpy(op->state.ps_consts_i, state->ps_consts_i, sizeof(op->state.ps_consts_i)); + + /* FIXME: This is not ideal. CS is still running synchronously, so this is ok. + * It will go away soon anyway. */ +@@ -1201,6 +1204,63 @@ void wined3d_cs_emit_set_consts_b(struct wined3d_cs *cs, UINT start_register, + cs->ops->submit(cs); + } + ++static UINT wined3d_cs_exec_set_vs_consts_i(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_set_consts_i *op = data; ++ struct wined3d_device *device = cs->device; ++ ++ memcpy(&cs->state.vs_consts_i[op->start_register * 4], op->constants, ++ sizeof(*cs->state.vs_consts_i) * 4 * op->vector4i_count); ++ ++ device_invalidate_shader_constants(device, WINED3D_SHADER_CONST_VS_I); ++ ++ return sizeof(*op) + sizeof(op->constants) * (op->vector4i_count - 1); ++} ++ ++static UINT wined3d_cs_exec_set_ps_consts_i(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_set_consts_i *op = data; ++ struct wined3d_device *device = cs->device; ++ ++ memcpy(&cs->state.ps_consts_i[op->start_register * 4], op->constants, ++ sizeof(*cs->state.ps_consts_i) * 4 * op->vector4i_count); ++ ++ device_invalidate_shader_constants(device, WINED3D_SHADER_CONST_PS_I); ++ ++ return sizeof(*op) + sizeof(op->constants) * (op->vector4i_count - 1); ++} ++ ++void wined3d_cs_emit_set_consts_i(struct wined3d_cs *cs, UINT start_register, ++ const int *constants, UINT vector4i_count, enum wined3d_shader_type type) ++{ ++ struct wined3d_cs_set_consts_i *op; ++ UINT extra_space = vector4i_count - 1; ++ ++ op = cs->ops->require_space(cs, sizeof(*op) + sizeof(op->constants) * extra_space); ++ switch (type) ++ { ++ case WINED3D_SHADER_TYPE_PIXEL: ++ op->opcode = WINED3D_CS_OP_SET_PS_CONSTS_I; ++ break; ++ ++ case WINED3D_SHADER_TYPE_VERTEX: ++ op->opcode = WINED3D_CS_OP_SET_VS_CONSTS_I; ++ break; ++ ++ case WINED3D_SHADER_TYPE_GEOMETRY: ++ ERR("Invalid for geometry shaders\n"); ++ return; ++ ++ case WINED3D_SHADER_TYPE_COUNT: ++ break; ++ } ++ op->start_register = start_register; ++ op->vector4i_count = vector4i_count; ++ memcpy(op->constants, constants, sizeof(op->constants) * vector4i_count); ++ ++ cs->ops->submit(cs); ++} ++ + static UINT wined3d_cs_exec_set_texture_state(struct wined3d_cs *cs, const void *data) + { + const struct wined3d_cs_set_texture_state *op = data; +@@ -1442,8 +1502,10 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* WINED3D_CS_OP_STATEBLOCK */ wined3d_cs_exec_transfer_stateblock, + /* 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, +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index 14d3080..9ba40df 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -2278,7 +2278,8 @@ HRESULT CDECL wined3d_device_set_vs_consts_i(struct wined3d_device *device, + } + else + { +- device_invalidate_shader_constants(device, WINED3D_SHADER_CONST_VS_I); ++ wined3d_cs_emit_set_consts_i(device->cs, start_register, constants, ++ vector4i_count, WINED3D_SHADER_TYPE_VERTEX); + } + + return WINED3D_OK; +@@ -2513,7 +2514,8 @@ HRESULT CDECL wined3d_device_set_ps_consts_i(struct wined3d_device *device, + } + else + { +- device_invalidate_shader_constants(device, WINED3D_SHADER_CONST_PS_I); ++ wined3d_cs_emit_set_consts_i(device->cs, start_register, constants, ++ vector4i_count, WINED3D_SHADER_TYPE_PIXEL); + } + + return WINED3D_OK; +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 4ecb626..59149bd 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2618,6 +2618,8 @@ void wined3d_cs_emit_set_consts_f(struct wined3d_cs *cs, UINT start_register, co + UINT vector4f_count, enum wined3d_shader_type type) DECLSPEC_HIDDEN; + void wined3d_cs_emit_set_consts_b(struct wined3d_cs *cs, UINT start_register, + const BOOL *constants, UINT bool_count, enum wined3d_shader_type type) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_set_consts_i(struct wined3d_cs *cs, UINT start_register, ++ const int *constants, UINT vector4i_count, enum wined3d_shader_type type) DECLSPEC_HIDDEN; + void wined3d_cs_emit_glfinish(struct wined3d_cs *cs) DECLSPEC_HIDDEN; + void wined3d_cs_emit_set_base_vertex_index(struct wined3d_cs *cs, + UINT base_vertex_index) DECLSPEC_HIDDEN; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0068-wined3d-Send-light-updates-through-the-command-strea.patch b/patches/wined3d-CSMT_Main/0068-wined3d-Send-light-updates-through-the-command-strea.patch new file mode 100644 index 00000000..3a28c6ce --- /dev/null +++ b/patches/wined3d-CSMT_Main/0068-wined3d-Send-light-updates-through-the-command-strea.patch @@ -0,0 +1,394 @@ +From 8ca77cbd15b2c770395d2f8d4dfc7d1eb05fc131 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Wed, 10 Apr 2013 17:16:02 +0200 +Subject: wined3d: Send light updates through the command stream + +--- + dlls/wined3d/cs.c | 200 +++++++++++++++++++++++++++++++++-------- + dlls/wined3d/device.c | 31 ++----- + dlls/wined3d/wined3d_private.h | 8 +- + 3 files changed, 174 insertions(+), 65 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index cf3a523..f48d14a 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -62,7 +62,6 @@ enum wined3d_cs_op + WINED3D_CS_OP_SET_CLIP_PLANE, + WINED3D_CS_OP_SET_MATERIAL, + WINED3D_CS_OP_RESET_STATE, +- WINED3D_CS_OP_STATEBLOCK, + WINED3D_CS_OP_SET_VS_CONSTS_F, + WINED3D_CS_OP_SET_VS_CONSTS_B, + WINED3D_CS_OP_SET_VS_CONSTS_I, +@@ -72,6 +71,8 @@ enum wined3d_cs_op + WINED3D_CS_OP_GLFINISH, + WINED3D_CS_OP_SET_BASE_VERTEX_INDEX, + WINED3D_CS_OP_SET_PRIMITIVE_TYPE, ++ WINED3D_CS_OP_SET_LIGHT, ++ WINED3D_CS_OP_SET_LIGHT_ENABLE, + WINED3D_CS_OP_STOP, + }; + +@@ -278,12 +279,6 @@ struct wined3d_cs_reset_state + enum wined3d_cs_op opcode; + }; + +-struct wined3d_cs_stateblock +-{ +- enum wined3d_cs_op opcode; +- struct wined3d_state state; +-}; +- + struct wined3d_cs_set_consts_f + { + enum wined3d_cs_op opcode; +@@ -322,6 +317,19 @@ struct wined3d_cs_set_primitive_type + GLenum gl_primitive_type; + }; + ++struct wined3d_cs_set_light ++{ ++ enum wined3d_cs_op opcode; ++ struct wined3d_light_info light; ++}; ++ ++struct wined3d_cs_set_light_enable ++{ ++ enum wined3d_cs_op opcode; ++ UINT idx; ++ BOOL enable; ++}; ++ + /* FIXME: The list synchronization probably isn't particularly fast. */ + static void wined3d_cs_list_enqueue(struct wined3d_cs_list *list, struct wined3d_cs_block *block) + { +@@ -971,35 +979,6 @@ void wined3d_cs_emit_set_texture(struct wined3d_cs *cs, UINT stage, struct wined + cs->ops->submit(cs); + } + +-static UINT wined3d_cs_exec_transfer_stateblock(struct wined3d_cs *cs, const void *data) +-{ +- const struct wined3d_cs_stateblock *op = data; +- +- /* Don't memcpy the entire struct, we'll remove single items as we add dedicated +- * ops for setting states */ +- +- memcpy(cs->state.lights, op->state.lights, sizeof(cs->state.lights)); +- +- return sizeof(*op); +-} +- +-void wined3d_cs_emit_transfer_stateblock(struct wined3d_cs *cs, const struct wined3d_state *state) +-{ +- struct wined3d_cs_stateblock *op; +- +- op = cs->ops->require_space(cs, sizeof(*op)); +- op->opcode = WINED3D_CS_OP_STATEBLOCK; +- +- /* Don't memcpy the entire struct, we'll remove single items as we add dedicated +- * ops for setting states */ +- +- /* FIXME: This is not ideal. CS is still running synchronously, so this is ok. +- * It will go away soon anyway. */ +- memcpy(op->state.lights, state->lights, sizeof(op->state.lights)); +- +- cs->ops->submit(cs); +-} +- + static UINT wined3d_cs_exec_set_shader_resource_view(struct wined3d_cs *cs, const void *data) + { + const struct wined3d_cs_set_shader_resource_view *op = data; +@@ -1471,6 +1450,152 @@ void wined3d_cs_emit_set_primitive_type(struct wined3d_cs *cs, GLenum primitive_ + cs->ops->submit(cs); + } + ++static UINT wined3d_cs_exec_set_light(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_set_light *op = data; ++ ++ UINT light_idx = op->light.OriginalIndex; ++ UINT hash_idx = LIGHTMAP_HASHFUNC(op->light.OriginalIndex); ++ struct wined3d_light_info *object = NULL; ++ struct list *e; ++ ++ LIST_FOR_EACH(e, &cs->state.light_map[hash_idx]) ++ { ++ object = LIST_ENTRY(e, struct wined3d_light_info, entry); ++ if (object->OriginalIndex == light_idx) ++ break; ++ object = NULL; ++ } ++ ++ if (!object) ++ { ++ TRACE("Adding new light\n"); ++ object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); ++ if (!object) ++ return E_OUTOFMEMORY; ++ ++ list_add_head(&cs->state.light_map[hash_idx], &object->entry); ++ object->glIndex = -1; ++ object->OriginalIndex = light_idx; ++ } ++ ++ object->OriginalParms = op->light.OriginalParms; ++ memcpy(object->lightPosn, op->light.lightPosn, sizeof(object->lightPosn)); ++ memcpy(object->lightDirn, op->light.lightDirn, sizeof(object->lightDirn)); ++ object->exponent = op->light.exponent; ++ object->cutoff = op->light.cutoff; ++ ++ /* Update the live definitions if the light is currently assigned a glIndex. */ ++ if (object->glIndex != -1) ++ { ++ if (object->OriginalParms.type != op->light.OriginalParms.type) ++ device_invalidate_state(cs->device, STATE_LIGHT_TYPE); ++ device_invalidate_state(cs->device, STATE_ACTIVELIGHT(object->glIndex)); ++ } ++ ++ return sizeof(*op); ++} ++ ++void wined3d_cs_emit_set_light(struct wined3d_cs *cs, const struct wined3d_light_info *light) ++{ ++ struct wined3d_cs_set_light *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_SET_LIGHT; ++ op->light = *light; ++ ++ cs->ops->submit(cs); ++} ++ ++static UINT wined3d_cs_exec_set_light_enable(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_set_light_enable *op = data; ++ UINT hash_idx = LIGHTMAP_HASHFUNC(op->idx); ++ struct wined3d_light_info *light_info = NULL; ++ struct list *e; ++ struct wined3d_device *device = cs->device; ++ ++ LIST_FOR_EACH(e, &cs->state.light_map[hash_idx]) ++ { ++ light_info = LIST_ENTRY(e, struct wined3d_light_info, entry); ++ if (light_info->OriginalIndex == op->idx) ++ break; ++ light_info = NULL; ++ } ++ TRACE("Found light %p.\n", light_info); ++ ++ /* Should be handled by the device by emitting a set_light op */ ++ if (!light_info) ++ { ++ ERR("Light enabled requested but light not defined in cs state!\n"); ++ return sizeof(*op); ++ } ++ ++ if (!op->enable) ++ { ++ if (light_info->glIndex != -1) ++ { ++ device_invalidate_state(device, STATE_LIGHT_TYPE); ++ device_invalidate_state(device, STATE_ACTIVELIGHT(light_info->glIndex)); ++ cs->state.lights[light_info->glIndex] = NULL; ++ light_info->glIndex = -1; ++ } ++ else ++ { ++ TRACE("Light already disabled, nothing to do\n"); ++ } ++ light_info->enabled = FALSE; ++ } ++ else ++ { ++ light_info->enabled = TRUE; ++ if (light_info->glIndex != -1) ++ { ++ TRACE("Nothing to do as light was enabled\n"); ++ } ++ else ++ { ++ unsigned int i; ++ const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; ++ /* Find a free GL light. */ ++ for (i = 0; i < gl_info->limits.lights; ++i) ++ { ++ if (!cs->state.lights[i]) ++ { ++ cs->state.lights[i] = light_info; ++ light_info->glIndex = i; ++ break; ++ } ++ } ++ if (light_info->glIndex == -1) ++ { ++ /* Should be caught by the device before emitting ++ * the light_enable op */ ++ ERR("Too many concurrently active lights in cs\n"); ++ return sizeof(*op); ++ } ++ ++ /* i == light_info->glIndex */ ++ device_invalidate_state(device, STATE_LIGHT_TYPE); ++ device_invalidate_state(device, STATE_ACTIVELIGHT(i)); ++ } ++ } ++ ++ return sizeof(*op); ++} ++ ++void wined3d_cs_emit_set_light_enable(struct wined3d_cs *cs, UINT idx, BOOL enable) ++{ ++ struct wined3d_cs_set_light_enable *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_SET_LIGHT_ENABLE; ++ op->idx = idx; ++ op->enable = enable; ++ ++ cs->ops->submit(cs); ++} ++ + static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = + { + /* WINED3D_CS_OP_FENCE */ wined3d_cs_exec_fence, +@@ -1499,7 +1624,6 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* WINED3D_CS_OP_SET_CLIP_PLANE */ wined3d_cs_exec_set_clip_plane, + /* WINED3D_CS_OP_SET_MATERIAL */ wined3d_cs_exec_set_material, + /* WINED3D_CS_OP_RESET_STATE */ wined3d_cs_exec_reset_state, +- /* WINED3D_CS_OP_STATEBLOCK */ wined3d_cs_exec_transfer_stateblock, + /* 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, +@@ -1509,6 +1633,8 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* 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, + }; + + static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size) +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index 9ba40df..05a353c 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -1448,14 +1448,6 @@ HRESULT CDECL wined3d_device_set_light(struct wined3d_device *device, + TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", + light->range, light->falloff, light->theta, light->phi); + +- /* Update the live definitions if the light is currently assigned a glIndex. */ +- if (object->glIndex != -1 && !device->recording) +- { +- if (object->OriginalParms.type != light->type) +- device_invalidate_state(device, STATE_LIGHT_TYPE); +- device_invalidate_state(device, STATE_ACTIVELIGHT(object->glIndex)); +- } +- + /* Save away the information. */ + object->OriginalParms = *light; + +@@ -1528,6 +1520,9 @@ HRESULT CDECL wined3d_device_set_light(struct wined3d_device *device, + FIXME("Unrecognized light type %#x.\n", light->type); + } + ++ if (!device->recording) ++ wined3d_cs_emit_set_light(device->cs, object); ++ + return WINED3D_OK; + } + +@@ -1600,12 +1595,6 @@ HRESULT CDECL wined3d_device_set_light_enable(struct wined3d_device *device, UIN + { + if (light_info->glIndex != -1) + { +- if (!device->recording) +- { +- device_invalidate_state(device, STATE_LIGHT_TYPE); +- device_invalidate_state(device, STATE_ACTIVELIGHT(light_info->glIndex)); +- } +- + device->update_state->lights[light_info->glIndex] = NULL; + light_info->glIndex = -1; + } +@@ -1647,16 +1636,12 @@ HRESULT CDECL wined3d_device_set_light_enable(struct wined3d_device *device, UIN + WARN("Too many concurrently active lights\n"); + return WINED3D_OK; + } +- +- /* i == light_info->glIndex */ +- if (!device->recording) +- { +- device_invalidate_state(device, STATE_LIGHT_TYPE); +- device_invalidate_state(device, STATE_ACTIVELIGHT(i)); +- } + } + } + ++ if (!device->recording) ++ wined3d_cs_emit_set_light_enable(device->cs, light_idx, enable); ++ + return WINED3D_OK; + } + +@@ -3383,7 +3368,6 @@ HRESULT CDECL wined3d_device_draw_primitive(struct wined3d_device *device, UINT + return WINED3DERR_INVALIDCALL; + } + +- wined3d_cs_emit_transfer_stateblock(device->cs, &device->state); + wined3d_cs_emit_draw(device->cs, start_vertex, vertex_count, 0, 0, FALSE); + + return WINED3D_OK; +@@ -3409,8 +3393,6 @@ HRESULT CDECL wined3d_device_draw_indexed_primitive(struct wined3d_device *devic + return WINED3DERR_INVALIDCALL; + } + +- +- wined3d_cs_emit_transfer_stateblock(device->cs, &device->state); + wined3d_cs_emit_draw(device->cs, start_idx, index_count, 0, 0, TRUE); + + return WINED3D_OK; +@@ -3421,7 +3403,6 @@ void CDECL wined3d_device_draw_indexed_primitive_instanced(struct wined3d_device + { + TRACE("device %p, start_idx %u, index_count %u.\n", device, start_idx, index_count); + +- wined3d_cs_emit_transfer_stateblock(device->cs, &device->state); + wined3d_cs_emit_draw(device->cs, start_idx, index_count, start_instance, instance_count, TRUE); + } + +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 59149bd..54cf7b5 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2535,7 +2535,9 @@ struct wined3d_cs_block + { + struct list entry; + UINT pos; +- BYTE data[sizeof(struct wined3d_state) * 2]; /* FIXME? The size is somewhat arbitrary. */ ++ /* FIXME? The size is somewhat arbitrary. It's big enough for huge ++ * shader constant set calls though */ ++ BYTE data[sizeof(float) * 4 * 256 * 2]; + }; + + struct wined3d_cs_ops +@@ -2578,8 +2580,6 @@ void wined3d_cs_emit_set_clip_plane(struct wined3d_cs *cs, UINT plane_idx, + const struct wined3d_vec4 *plane) DECLSPEC_HIDDEN; + void wined3d_cs_emit_set_constant_buffer(struct wined3d_cs *cs, enum wined3d_shader_type type, + UINT cb_idx, struct wined3d_buffer *buffer) DECLSPEC_HIDDEN; +-void wined3d_cs_emit_transfer_stateblock(struct wined3d_cs *cs, +- const struct wined3d_state *state) DECLSPEC_HIDDEN; + void wined3d_cs_emit_set_depth_stencil_view(struct wined3d_cs *cs, + struct wined3d_rendertarget_view *view) DECLSPEC_HIDDEN; + void wined3d_cs_emit_set_index_buffer(struct wined3d_cs *cs, struct wined3d_buffer *buffer, +@@ -2625,6 +2625,8 @@ void wined3d_cs_emit_set_base_vertex_index(struct wined3d_cs *cs, + UINT base_vertex_index) DECLSPEC_HIDDEN; + void wined3d_cs_emit_set_primitive_type(struct wined3d_cs *cs, + GLenum primitive_type) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_set_light(struct wined3d_cs *cs, const struct wined3d_light_info *light) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_set_light_enable(struct wined3d_cs *cs, UINT idx, BOOL enable) DECLSPEC_HIDDEN; + + /* 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 +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0069-wined3d-Prevent-the-command-stream-from-running-ahea.patch b/patches/wined3d-CSMT_Main/0069-wined3d-Prevent-the-command-stream-from-running-ahea.patch new file mode 100644 index 00000000..f8ca114f --- /dev/null +++ b/patches/wined3d-CSMT_Main/0069-wined3d-Prevent-the-command-stream-from-running-ahea.patch @@ -0,0 +1,60 @@ +From 0fe58ec92cc169b54b6d1f579ee59f70aa4554d0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Wed, 10 Apr 2013 19:10:41 +0200 +Subject: wined3d: Prevent the command stream from running ahead too far + +--- + dlls/wined3d/cs.c | 8 ++++++++ + dlls/wined3d/wined3d_private.h | 2 ++ + 2 files changed, 10 insertions(+) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index f48d14a..dbfd86d 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -472,6 +472,8 @@ static UINT wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data) + src_rect, dst_rect, dirty_region, op->flags, + wined3d_rendertarget_view_get_surface(cs->state.fb.depth_stencil)); + ++ InterlockedDecrement(&cs->pending_presents); ++ + return sizeof(*op); + } + +@@ -480,6 +482,7 @@ void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *sw + const RGNDATA *dirty_region, DWORD flags) + { + struct wined3d_cs_present *op; ++ LONG pending; + + op = cs->ops->require_space(cs, sizeof(*op)); + op->opcode = WINED3D_CS_OP_PRESENT; +@@ -503,7 +506,12 @@ void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *sw + } + op->flags = flags; + ++ pending = InterlockedIncrement(&cs->pending_presents); ++ + cs->ops->submit(cs); ++ ++ while (pending > 1) ++ pending = InterlockedCompareExchange(&cs->pending_presents, 0, 0); + } + + static UINT wined3d_cs_exec_clear(struct wined3d_cs *cs, const void *data) +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 54cf7b5..ab3d07f 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2561,6 +2561,8 @@ struct wined3d_cs + + struct wined3d_cs_list free_list; + struct wined3d_cs_list exec_list; ++ ++ LONG pending_presents; + }; + + struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device) DECLSPEC_HIDDEN; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0070-wined3d-Wait-for-the-cs-to-finish-before-destroying-.patch b/patches/wined3d-CSMT_Main/0070-wined3d-Wait-for-the-cs-to-finish-before-destroying-.patch new file mode 100644 index 00000000..c16df54f --- /dev/null +++ b/patches/wined3d-CSMT_Main/0070-wined3d-Wait-for-the-cs-to-finish-before-destroying-.patch @@ -0,0 +1,26 @@ +From 0f21b13a057d684fa30678d8c08e87614eca066a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Wed, 10 Apr 2013 20:09:55 +0200 +Subject: wined3d: Wait for the cs to finish before destroying the device + +--- + dlls/wined3d/device.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index 05a353c..9ef99b2 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -1013,6 +1013,9 @@ HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device) + if (!device->d3d_initialized) + return WINED3DERR_INVALIDCALL; + ++ if (wined3d_settings.cs_multithreaded) ++ device->cs->ops->finish(device->cs); ++ + /* I don't think that the interface guarantees that the device is destroyed from the same thread + * it was created. Thus make sure a context is active for the glDelete* calls + */ +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0071-wined3d-Run-the-cs-asynchronously.patch b/patches/wined3d-CSMT_Main/0071-wined3d-Run-the-cs-asynchronously.patch new file mode 100644 index 00000000..f11c46d9 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0071-wined3d-Run-the-cs-asynchronously.patch @@ -0,0 +1,25 @@ +From ae49b3a304769185e9f2a92ec21975d44a389654 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Wed, 10 Apr 2013 20:12:27 +0200 +Subject: wined3d: Run the cs asynchronously + +--- + dlls/wined3d/cs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index dbfd86d..949bd6b 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -1679,7 +1679,7 @@ static const struct wined3d_cs_ops wined3d_cs_st_ops = + static const struct wined3d_cs_ops wined3d_cs_mt_ops = + { + wined3d_cs_mt_require_space, +- wined3d_cs_flush_and_wait, ++ wined3d_cs_flush, + wined3d_cs_flush_and_wait, + }; + +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0072-wined3d-Send-blits-through-the-command-stream.patch b/patches/wined3d-CSMT_Main/0072-wined3d-Send-blits-through-the-command-stream.patch new file mode 100644 index 00000000..21331928 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0072-wined3d-Send-blits-through-the-command-stream.patch @@ -0,0 +1,555 @@ +From f2f3b1c84b57d393a2eb2986704537d37d81f04b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Mon, 29 Apr 2013 18:49:53 +0200 +Subject: wined3d: Send blits through the command stream. + +This needs more work. This patch breaks error handling, and the split +between surface_blt and surface_blt_ugly isn't particularly nice. +--- + dlls/wined3d/cs.c | 50 +++++++ + dlls/wined3d/surface.c | 307 ++++++++++++++++++++++------------------- + dlls/wined3d/wined3d_private.h | 8 ++ + 3 files changed, 226 insertions(+), 139 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 949bd6b..dcaedfd 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -73,6 +73,7 @@ enum wined3d_cs_op + WINED3D_CS_OP_SET_PRIMITIVE_TYPE, + WINED3D_CS_OP_SET_LIGHT, + WINED3D_CS_OP_SET_LIGHT_ENABLE, ++ WINED3D_CS_OP_BLT, + WINED3D_CS_OP_STOP, + }; + +@@ -330,6 +331,18 @@ struct wined3d_cs_set_light_enable + BOOL enable; + }; + ++struct wined3d_cs_blt ++{ ++ enum wined3d_cs_op opcode; ++ struct wined3d_surface *dst_surface; ++ RECT dst_rect; ++ struct wined3d_surface *src_surface; ++ RECT src_rect; ++ DWORD flags; ++ WINEDDBLTFX fx; ++ enum wined3d_texture_filter_type filter; ++}; ++ + /* FIXME: The list synchronization probably isn't particularly fast. */ + static void wined3d_cs_list_enqueue(struct wined3d_cs_list *list, struct wined3d_cs_block *block) + { +@@ -1393,6 +1406,9 @@ static UINT wined3d_cs_exec_glfinish(struct wined3d_cs *cs, const void *data) + struct wined3d_device *device = cs->device; + struct wined3d_context *context; + ++ if (!device->d3d_initialized) ++ return sizeof(*op); ++ + context = context_acquire(device, NULL); + context->gl_info->gl_ops.gl.p_glFinish(); + context_release(context); +@@ -1604,6 +1620,38 @@ void wined3d_cs_emit_set_light_enable(struct wined3d_cs *cs, UINT idx, BOOL enab + cs->ops->submit(cs); + } + ++static UINT wined3d_cs_exec_blt(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_blt *op = data; ++ ++ surface_blt_ugly(op->dst_surface, &op->dst_rect, ++ op->src_surface, &op->src_rect, ++ op->flags, &op->fx, op->filter); ++ ++ return sizeof(*op); ++} ++ ++void wined3d_cs_emit_blt(struct wined3d_cs *cs, struct wined3d_surface *dst_surface, ++ const RECT *dst_rect, struct wined3d_surface *src_surface, ++ const RECT *src_rect, DWORD flags, const WINEDDBLTFX *fx, ++ enum wined3d_texture_filter_type filter) ++{ ++ struct wined3d_cs_blt *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_BLT; ++ op->dst_surface = dst_surface; ++ op->dst_rect = *dst_rect; ++ op->src_surface = src_surface; ++ op->src_rect = *src_rect; ++ op->flags = flags; ++ op->filter = filter; ++ if (fx) ++ op->fx = *fx; ++ ++ cs->ops->submit(cs); ++} ++ + static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = + { + /* WINED3D_CS_OP_FENCE */ wined3d_cs_exec_fence, +@@ -1643,6 +1691,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* 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, + }; + + static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size) +@@ -1717,6 +1766,7 @@ static DWORD WINAPI wined3d_cs_run(void *thread_param) + + TRACE("Started.\n"); + ++ cs->thread_id = GetCurrentThreadId(); + for (;;) + { + struct wined3d_cs_block *block; +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 97450ef..2620570 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -4937,14 +4937,13 @@ const struct blit_shader cpu_blit = { + cpu_blit_depth_fill, + }; + +-HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst_rect_in, +- struct wined3d_surface *src_surface, const RECT *src_rect_in, DWORD flags, ++void surface_blt_ugly(struct wined3d_surface *dst_surface, const RECT *dst_rect, ++ struct wined3d_surface *src_surface, const RECT *src_rect, DWORD flags, + const WINEDDBLTFX *fx, enum wined3d_texture_filter_type filter) + { + struct wined3d_swapchain *src_swapchain, *dst_swapchain; + struct wined3d_device *device = dst_surface->resource.device; + DWORD src_ds_flags, dst_ds_flags; +- RECT src_rect, dst_rect; + BOOL scale, convert; + + static const DWORD simple_blit = WINEDDBLT_ASYNC +@@ -4953,111 +4952,6 @@ HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const REC + | WINEDDBLT_DEPTHFILL + | WINEDDBLT_DONOTWAIT; + +- TRACE("dst_surface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p, filter %s.\n", +- dst_surface, wine_dbgstr_rect(dst_rect_in), src_surface, wine_dbgstr_rect(src_rect_in), +- flags, fx, debug_d3dtexturefiltertype(filter)); +- TRACE("Usage is %s.\n", debug_d3dusage(dst_surface->resource.usage)); +- +- if (fx) +- { +- TRACE("dwSize %#x.\n", fx->dwSize); +- TRACE("dwDDFX %#x.\n", fx->dwDDFX); +- TRACE("dwROP %#x.\n", fx->dwROP); +- TRACE("dwDDROP %#x.\n", fx->dwDDROP); +- TRACE("dwRotationAngle %#x.\n", fx->dwRotationAngle); +- TRACE("dwZBufferOpCode %#x.\n", fx->dwZBufferOpCode); +- TRACE("dwZBufferLow %#x.\n", fx->dwZBufferLow); +- TRACE("dwZBufferHigh %#x.\n", fx->dwZBufferHigh); +- TRACE("dwZBufferBaseDest %#x.\n", fx->dwZBufferBaseDest); +- TRACE("dwZDestConstBitDepth %#x.\n", fx->dwZDestConstBitDepth); +- TRACE("lpDDSZBufferDest %p.\n", fx->u1.lpDDSZBufferDest); +- TRACE("dwZSrcConstBitDepth %#x.\n", fx->dwZSrcConstBitDepth); +- TRACE("lpDDSZBufferSrc %p.\n", fx->u2.lpDDSZBufferSrc); +- TRACE("dwAlphaEdgeBlendBitDepth %#x.\n", fx->dwAlphaEdgeBlendBitDepth); +- TRACE("dwAlphaEdgeBlend %#x.\n", fx->dwAlphaEdgeBlend); +- TRACE("dwReserved %#x.\n", fx->dwReserved); +- TRACE("dwAlphaDestConstBitDepth %#x.\n", fx->dwAlphaDestConstBitDepth); +- TRACE("lpDDSAlphaDest %p.\n", fx->u3.lpDDSAlphaDest); +- TRACE("dwAlphaSrcConstBitDepth %#x.\n", fx->dwAlphaSrcConstBitDepth); +- TRACE("lpDDSAlphaSrc %p.\n", fx->u4.lpDDSAlphaSrc); +- TRACE("lpDDSPattern %p.\n", fx->u5.lpDDSPattern); +- TRACE("ddckDestColorkey {%#x, %#x}.\n", +- fx->ddckDestColorkey.color_space_low_value, +- fx->ddckDestColorkey.color_space_high_value); +- TRACE("ddckSrcColorkey {%#x, %#x}.\n", +- fx->ddckSrcColorkey.color_space_low_value, +- fx->ddckSrcColorkey.color_space_high_value); +- } +- +- if (dst_surface->resource.map_count || (src_surface && src_surface->resource.map_count)) +- { +- WARN("Surface is busy, returning WINEDDERR_SURFACEBUSY.\n"); +- return WINEDDERR_SURFACEBUSY; +- } +- +- surface_get_rect(dst_surface, dst_rect_in, &dst_rect); +- +- if (dst_rect.left >= dst_rect.right || dst_rect.top >= dst_rect.bottom +- || dst_rect.left > dst_surface->resource.width || dst_rect.left < 0 +- || dst_rect.top > dst_surface->resource.height || dst_rect.top < 0 +- || dst_rect.right > dst_surface->resource.width || dst_rect.right < 0 +- || dst_rect.bottom > dst_surface->resource.height || dst_rect.bottom < 0) +- { +- WARN("The application gave us a bad destination rectangle.\n"); +- return WINEDDERR_INVALIDRECT; +- } +- +- if (src_surface) +- { +- surface_get_rect(src_surface, src_rect_in, &src_rect); +- +- if (src_rect.left >= src_rect.right || src_rect.top >= src_rect.bottom +- || src_rect.left > src_surface->resource.width || src_rect.left < 0 +- || src_rect.top > src_surface->resource.height || src_rect.top < 0 +- || src_rect.right > src_surface->resource.width || src_rect.right < 0 +- || src_rect.bottom > src_surface->resource.height || src_rect.bottom < 0) +- { +- WARN("Application gave us bad source rectangle for Blt.\n"); +- return WINEDDERR_INVALIDRECT; +- } +- } +- else +- { +- memset(&src_rect, 0, sizeof(src_rect)); +- } +- +- if (!fx || !(fx->dwDDFX)) +- flags &= ~WINEDDBLT_DDFX; +- +- if (flags & WINEDDBLT_WAIT) +- flags &= ~WINEDDBLT_WAIT; +- +- if (flags & WINEDDBLT_ASYNC) +- { +- static unsigned int once; +- +- if (!once++) +- FIXME("Can't handle WINEDDBLT_ASYNC flag.\n"); +- flags &= ~WINEDDBLT_ASYNC; +- } +- +- /* WINEDDBLT_DONOTWAIT appeared in DX7. */ +- if (flags & WINEDDBLT_DONOTWAIT) +- { +- static unsigned int once; +- +- if (!once++) +- FIXME("Can't handle WINEDDBLT_DONOTWAIT flag.\n"); +- flags &= ~WINEDDBLT_DONOTWAIT; +- } +- +- if (wined3d_settings.cs_multithreaded) +- { +- FIXME("Waiting for cs.\n"); +- wined3d_cs_emit_glfinish(device->cs); +- device->cs->ops->finish(device->cs); +- } +- + if (!device->d3d_initialized) + { + WARN("D3D not initialized, using fallback.\n"); +@@ -5100,8 +4994,8 @@ HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const REC + } + + scale = src_surface +- && (src_rect.right - src_rect.left != dst_rect.right - dst_rect.left +- || src_rect.bottom - src_rect.top != dst_rect.bottom - dst_rect.top); ++ && (src_rect->right - src_rect->left != dst_rect->right - dst_rect->left ++ || src_rect->bottom - src_rect->top != dst_rect->bottom - dst_rect->top); + convert = src_surface && src_surface->resource.format->id != dst_surface->resource.format->id; + + dst_ds_flags = dst_surface->resource.format->flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL); +@@ -5119,22 +5013,16 @@ HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const REC + TRACE("Depth fill.\n"); + + if (!surface_convert_depth_to_float(dst_surface, fx->u5.dwFillDepth, &depth)) +- return WINED3DERR_INVALIDCALL; ++ return; + +- if (SUCCEEDED(wined3d_surface_depth_fill(dst_surface, &dst_rect, depth))) +- return WINED3D_OK; ++ if (SUCCEEDED(wined3d_surface_depth_fill(dst_surface, dst_rect, depth))) ++ return; + } + else + { +- if (src_ds_flags != dst_ds_flags) +- { +- WARN("Rejecting depth / stencil blit between incompatible formats.\n"); +- return WINED3DERR_INVALIDCALL; +- } +- + if (SUCCEEDED(wined3d_surface_depth_blt(src_surface, src_surface->container->resource.draw_binding, +- &src_rect, dst_surface, dst_surface->container->resource.draw_binding, &dst_rect))) +- return WINED3D_OK; ++ src_rect, dst_surface, dst_surface->container->resource.draw_binding, dst_rect))) ++ return; + } + } + else +@@ -5161,8 +5049,8 @@ HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const REC + if (!surface_convert_color_to_float(dst_surface, fx->u5.dwFillColor, &color)) + goto fallback; + +- if (SUCCEEDED(surface_color_fill(dst_surface, &dst_rect, &color))) +- return WINED3D_OK; ++ if (SUCCEEDED(surface_color_fill(dst_surface, dst_rect, &color))) ++ return; + } + else + { +@@ -5178,9 +5066,9 @@ HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const REC + TRACE("Not doing upload because of format conversion.\n"); + else + { +- POINT dst_point = {dst_rect.left, dst_rect.top}; ++ POINT dst_point = {dst_rect->left, dst_rect->top}; + +- if (SUCCEEDED(surface_upload_from_surface(dst_surface, &dst_point, src_surface, &src_rect))) ++ if (SUCCEEDED(surface_upload_from_surface(dst_surface, &dst_point, src_surface, src_rect))) + { + if (!wined3d_resource_is_offscreen(&dst_surface->container->resource)) + { +@@ -5189,7 +5077,7 @@ HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const REC + dst_surface->container->resource.draw_binding); + context_release(context); + } +- return WINED3D_OK; ++ return; + } + } + } +@@ -5214,51 +5102,192 @@ HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const REC + wined3d_swapchain_present(dst_swapchain, NULL, NULL, dst_swapchain->win_handle, NULL, 0); + dst_swapchain->desc.swap_effect = swap_effect; + +- return WINED3D_OK; ++ return; + } + + if (fbo_blit_supported(&device->adapter->gl_info, WINED3D_BLIT_OP_COLOR_BLIT, +- &src_rect, src_surface->resource.usage, src_surface->resource.pool, src_surface->resource.format, +- &dst_rect, dst_surface->resource.usage, dst_surface->resource.pool, dst_surface->resource.format)) ++ src_rect, src_surface->resource.usage, src_surface->resource.pool, src_surface->resource.format, ++ dst_rect, dst_surface->resource.usage, dst_surface->resource.pool, dst_surface->resource.format)) + { + struct wined3d_context *context; + TRACE("Using FBO blit.\n"); + + context = context_acquire(device, NULL); + surface_blt_fbo(device, context, filter, +- src_surface, src_surface->container->resource.draw_binding, &src_rect, +- dst_surface, dst_surface->container->resource.draw_binding, &dst_rect); ++ src_surface, src_surface->container->resource.draw_binding, src_rect, ++ dst_surface, dst_surface->container->resource.draw_binding, dst_rect); + context_release(context); + + wined3d_resource_validate_location(&dst_surface->resource, dst_surface->container->resource.draw_binding); + wined3d_resource_invalidate_location(&dst_surface->resource, ~dst_surface->container->resource.draw_binding); + +- return WINED3D_OK; ++ return; + } + + if (arbfp_blit.blit_supported(&device->adapter->gl_info, WINED3D_BLIT_OP_COLOR_BLIT, +- &src_rect, src_surface->resource.usage, src_surface->resource.pool, src_surface->resource.format, +- &dst_rect, dst_surface->resource.usage, dst_surface->resource.pool, dst_surface->resource.format)) ++ src_rect, src_surface->resource.usage, src_surface->resource.pool, src_surface->resource.format, ++ dst_rect, dst_surface->resource.usage, dst_surface->resource.pool, dst_surface->resource.format)) + { + TRACE("Using arbfp blit.\n"); + +- if (SUCCEEDED(arbfp_blit_surface(device, filter, src_surface, &src_rect, dst_surface, &dst_rect))) +- return WINED3D_OK; ++ if (SUCCEEDED(arbfp_blit_surface(device, filter, src_surface, src_rect, dst_surface, dst_rect))) ++ return; + } + } + } + + fallback: + /* Special cases for render targets. */ +- if (SUCCEEDED(surface_blt_special(dst_surface, &dst_rect, src_surface, &src_rect, flags, fx, filter))) +- return WINED3D_OK; ++ if ((dst_surface->resource.usage & WINED3DUSAGE_RENDERTARGET) ++ || (src_surface && (src_surface->resource.usage & WINED3DUSAGE_RENDERTARGET))) ++ { ++ if (SUCCEEDED(surface_blt_special(dst_surface, dst_rect, src_surface, src_rect, flags, fx, filter))) ++ return; ++ } + + cpu: + + /* For the rest call the X11 surface implementation. For render targets + * this should be implemented OpenGL accelerated in surface_blt_special(), + * other blits are rather rare. */ +- return surface_cpu_blt(dst_surface, &dst_rect, src_surface, &src_rect, flags, fx, filter); ++ surface_cpu_blt(dst_surface, dst_rect, src_surface, src_rect, flags, fx, filter); ++ return; ++} ++ ++HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst_rect_in, ++ struct wined3d_surface *src_surface, const RECT *src_rect_in, DWORD flags, ++ const WINEDDBLTFX *fx, enum wined3d_texture_filter_type filter) ++{ ++ struct wined3d_device *device = dst_surface->resource.device; ++ RECT src_rect, dst_rect; ++ ++ TRACE("dst_surface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p, filter %s.\n", ++ dst_surface, wine_dbgstr_rect(dst_rect_in), src_surface, wine_dbgstr_rect(src_rect_in), ++ flags, fx, debug_d3dtexturefiltertype(filter)); ++ TRACE("Usage is %s.\n", debug_d3dusage(dst_surface->resource.usage)); ++ ++ if (fx) ++ { ++ TRACE("dwSize %#x.\n", fx->dwSize); ++ TRACE("dwDDFX %#x.\n", fx->dwDDFX); ++ TRACE("dwROP %#x.\n", fx->dwROP); ++ TRACE("dwDDROP %#x.\n", fx->dwDDROP); ++ TRACE("dwRotationAngle %#x.\n", fx->dwRotationAngle); ++ TRACE("dwZBufferOpCode %#x.\n", fx->dwZBufferOpCode); ++ TRACE("dwZBufferLow %#x.\n", fx->dwZBufferLow); ++ TRACE("dwZBufferHigh %#x.\n", fx->dwZBufferHigh); ++ TRACE("dwZBufferBaseDest %#x.\n", fx->dwZBufferBaseDest); ++ TRACE("dwZDestConstBitDepth %#x.\n", fx->dwZDestConstBitDepth); ++ TRACE("lpDDSZBufferDest %p.\n", fx->u1.lpDDSZBufferDest); ++ TRACE("dwZSrcConstBitDepth %#x.\n", fx->dwZSrcConstBitDepth); ++ TRACE("lpDDSZBufferSrc %p.\n", fx->u2.lpDDSZBufferSrc); ++ TRACE("dwAlphaEdgeBlendBitDepth %#x.\n", fx->dwAlphaEdgeBlendBitDepth); ++ TRACE("dwAlphaEdgeBlend %#x.\n", fx->dwAlphaEdgeBlend); ++ TRACE("dwReserved %#x.\n", fx->dwReserved); ++ TRACE("dwAlphaDestConstBitDepth %#x.\n", fx->dwAlphaDestConstBitDepth); ++ TRACE("lpDDSAlphaDest %p.\n", fx->u3.lpDDSAlphaDest); ++ TRACE("dwAlphaSrcConstBitDepth %#x.\n", fx->dwAlphaSrcConstBitDepth); ++ TRACE("lpDDSAlphaSrc %p.\n", fx->u4.lpDDSAlphaSrc); ++ TRACE("lpDDSPattern %p.\n", fx->u5.lpDDSPattern); ++ TRACE("ddckDestColorkey {%#x, %#x}.\n", ++ fx->ddckDestColorkey.color_space_low_value, ++ fx->ddckDestColorkey.color_space_high_value); ++ TRACE("ddckSrcColorkey {%#x, %#x}.\n", ++ fx->ddckSrcColorkey.color_space_low_value, ++ fx->ddckSrcColorkey.color_space_high_value); ++ } ++ ++ if (dst_surface->resource.map_count || (src_surface && src_surface->resource.map_count)) ++ { ++ /* TODO: Separate application maps from internal maps */ ++ if (!wined3d_settings.cs_multithreaded) ++ { ++ WARN("Surface is busy, returning WINEDDERR_SURFACEBUSY.\n"); ++ return WINEDDERR_SURFACEBUSY; ++ } ++ ++ wined3d_cs_emit_glfinish(dst_surface->resource.device->cs); ++ dst_surface->resource.device->cs->ops->finish(dst_surface->resource.device->cs); ++ ++ if (dst_surface->resource.map_count || (src_surface && src_surface->resource.map_count)) ++ { ++ WARN("Surface is busy, returning WINEDDERR_SURFACEBUSY.\n"); ++ return WINEDDERR_SURFACEBUSY; ++ } ++ } ++ ++ surface_get_rect(dst_surface, dst_rect_in, &dst_rect); ++ ++ if (dst_rect.left >= dst_rect.right || dst_rect.top >= dst_rect.bottom ++ || dst_rect.left > dst_surface->resource.width || dst_rect.left < 0 ++ || dst_rect.top > dst_surface->resource.height || dst_rect.top < 0 ++ || dst_rect.right > dst_surface->resource.width || dst_rect.right < 0 ++ || dst_rect.bottom > dst_surface->resource.height || dst_rect.bottom < 0) ++ { ++ WARN("The application gave us a bad destination rectangle.\n"); ++ return WINEDDERR_INVALIDRECT; ++ } ++ ++ if (src_surface) ++ { ++ DWORD src_ds_flags, dst_ds_flags; ++ ++ surface_get_rect(src_surface, src_rect_in, &src_rect); ++ ++ if (src_rect.left >= src_rect.right || src_rect.top >= src_rect.bottom ++ || src_rect.left > src_surface->resource.width || src_rect.left < 0 ++ || src_rect.top > src_surface->resource.height || src_rect.top < 0 ++ || src_rect.right > src_surface->resource.width || src_rect.right < 0 ++ || src_rect.bottom > src_surface->resource.height || src_rect.bottom < 0) ++ { ++ WARN("Application gave us bad source rectangle for Blt.\n"); ++ return WINEDDERR_INVALIDRECT; ++ } ++ ++ dst_ds_flags = dst_surface->resource.format->flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL); ++ src_ds_flags = src_surface->resource.format->flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL); ++ if (src_ds_flags != dst_ds_flags) ++ { ++ WARN("Rejecting depth / stencil blit between incompatible formats.\n"); ++ return WINED3DERR_INVALIDCALL; ++ } ++ ++ } ++ else ++ { ++ memset(&src_rect, 0, sizeof(src_rect)); ++ } ++ ++ if (!fx || !(fx->dwDDFX)) ++ flags &= ~WINEDDBLT_DDFX; ++ ++ if (flags & WINEDDBLT_WAIT) ++ flags &= ~WINEDDBLT_WAIT; ++ ++ if (flags & WINEDDBLT_ASYNC) ++ { ++ static unsigned int once; ++ ++ if (!once++) ++ FIXME("Can't handle WINEDDBLT_ASYNC flag.\n"); ++ flags &= ~WINEDDBLT_ASYNC; ++ } ++ ++ /* WINEDDBLT_DONOTWAIT appeared in DX7. */ ++ if (flags & WINEDDBLT_DONOTWAIT) ++ { ++ static unsigned int once; ++ ++ if (!once++) ++ FIXME("Can't handle WINEDDBLT_DONOTWAIT flag.\n"); ++ flags &= ~WINEDDBLT_DONOTWAIT; ++ } ++ ++ TRACE("Emitting blit %p <== %p\n", dst_surface, src_surface); ++ wined3d_cs_emit_blt(device->cs, dst_surface, &dst_rect, src_surface, &src_rect, ++ flags, fx, filter); ++ ++ return WINED3D_OK; + } + + static const struct wined3d_resource_ops surface_resource_ops = +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index ab3d07f..a311a35 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2409,6 +2409,9 @@ HRESULT wined3d_surface_create(struct wined3d_texture *container, const struct w + 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_blt_ugly(struct wined3d_surface *dst_surface, const RECT *dst_rect_in, ++ struct wined3d_surface *src_surface, const RECT *src_rect_in, DWORD flags, ++ const WINEDDBLTFX *fx, enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN; + + 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; +@@ -2553,6 +2556,7 @@ struct wined3d_cs + struct wined3d_device *device; + struct wined3d_state state; + HANDLE thread; ++ DWORD thread_id; + DWORD tls_idx; + struct wined3d_surface *onscreen_depth_stencil; + +@@ -2629,6 +2633,10 @@ void wined3d_cs_emit_set_primitive_type(struct wined3d_cs *cs, + GLenum primitive_type) DECLSPEC_HIDDEN; + void wined3d_cs_emit_set_light(struct wined3d_cs *cs, const struct wined3d_light_info *light) DECLSPEC_HIDDEN; + void wined3d_cs_emit_set_light_enable(struct wined3d_cs *cs, UINT idx, BOOL enable) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_blt(struct wined3d_cs *cs, struct wined3d_surface *dst_surface, ++ const RECT *dst_rect, struct wined3d_surface *src_surface, ++ const RECT *src_rect, DWORD flags, const WINEDDBLTFX *fx, ++ enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN; + + /* 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 +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0073-wined3d-Put-update_surface-checks-back-in-place.patch b/patches/wined3d-CSMT_Main/0073-wined3d-Put-update_surface-checks-back-in-place.patch new file mode 100644 index 00000000..74e5b788 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0073-wined3d-Put-update_surface-checks-back-in-place.patch @@ -0,0 +1,125 @@ +From f563282c26b069e5e053bd2bc441fe079854f998 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Wed, 20 Aug 2014 14:14:23 +0200 +Subject: wined3d: Put update_surface checks back in place + +Unfortunately I can't remove the code from surface_update_from_surface +yet because blits depend on them. +--- + dlls/wined3d/device.c | 66 ++++++++++++++++++++++++++++++++++++++++++ + dlls/wined3d/surface.c | 2 +- + dlls/wined3d/wined3d_private.h | 1 + + 3 files changed, 68 insertions(+), 1 deletion(-) + +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index 9ef99b2..599a25d 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -3731,6 +3731,13 @@ HRESULT CDECL wined3d_device_update_surface(struct wined3d_device *device, + struct wined3d_surface *src_surface, const RECT *src_rect, + struct wined3d_surface *dst_surface, const POINT *dst_point) + { ++ const struct wined3d_format *src_format = src_surface->resource.format; ++ const struct wined3d_format *dst_format = dst_surface->resource.format; ++ UINT update_w, update_h; ++ UINT dst_w, dst_h; ++ RECT r, dst_rect; ++ POINT p; ++ + TRACE("device %p, src_surface %p, src_rect %s, dst_surface %p, dst_point %s.\n", + device, src_surface, wine_dbgstr_rect(src_rect), + dst_surface, wine_dbgstr_point(dst_point)); +@@ -3742,6 +3749,65 @@ HRESULT CDECL wined3d_device_update_surface(struct wined3d_device *device, + return WINED3DERR_INVALIDCALL; + } + ++ if (src_format->id != dst_format->id) ++ { ++ WARN("Source and destination surfaces should have the same format.\n"); ++ return WINED3DERR_INVALIDCALL; ++ } ++ ++ if (!dst_point) ++ { ++ p.x = 0; ++ p.y = 0; ++ dst_point = &p; ++ } ++ else if (dst_point->x < 0 || dst_point->y < 0) ++ { ++ WARN("Invalid destination point.\n"); ++ return WINED3DERR_INVALIDCALL; ++ } ++ ++ if (!src_rect) ++ { ++ r.left = 0; ++ r.top = 0; ++ r.right = src_surface->resource.width; ++ r.bottom = src_surface->resource.height; ++ src_rect = &r; ++ } ++ else if (src_rect->left < 0 || src_rect->left >= src_rect->right ++ || src_rect->top < 0 || src_rect->top >= src_rect->bottom) ++ { ++ WARN("Invalid source rectangle.\n"); ++ return WINED3DERR_INVALIDCALL; ++ } ++ ++ dst_w = dst_surface->resource.width; ++ dst_h = dst_surface->resource.height; ++ ++ update_w = src_rect->right - src_rect->left; ++ update_h = src_rect->bottom - src_rect->top; ++ ++ if (update_w > dst_w || dst_point->x > dst_w - update_w ++ || update_h > dst_h || dst_point->y > dst_h - update_h) ++ { ++ WARN("Destination out of bounds.\n"); ++ return WINED3DERR_INVALIDCALL; ++ } ++ ++ if ((src_format->flags & WINED3DFMT_FLAG_BLOCKS) && !surface_check_block_align(src_surface, src_rect)) ++ { ++ WARN("Source rectangle not block-aligned.\n"); ++ return WINED3DERR_INVALIDCALL; ++ } ++ ++ SetRect(&dst_rect, dst_point->x, dst_point->y, dst_point->x + update_w, dst_point->y + update_h); ++ if ((dst_format->flags & WINED3DFMT_FLAG_BLOCKS) && !surface_check_block_align(dst_surface, &dst_rect)) ++ { ++ WARN("Destination rectangle not block-aligned.\n"); ++ return WINED3DERR_INVALIDCALL; ++ } ++ + if (wined3d_settings.cs_multithreaded) + { + FIXME("Waiting for cs.\n"); +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 2620570..c47f78c 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -1420,7 +1420,7 @@ static void surface_upload_data(struct wined3d_surface *surface, const struct wi + } + } + +-static BOOL surface_check_block_align(struct wined3d_surface *surface, const RECT *rect) ++BOOL surface_check_block_align(struct wined3d_surface *surface, const RECT *rect) + { + struct wined3d_box box; + +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index a311a35..0d76377 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2412,6 +2412,7 @@ void wined3d_surface_destroy(struct wined3d_surface *surface) DECLSPEC_HIDDEN; + void surface_blt_ugly(struct wined3d_surface *dst_surface, const RECT *dst_rect_in, + struct wined3d_surface *src_surface, const RECT *src_rect_in, DWORD flags, + const WINEDDBLTFX *fx, enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN; ++BOOL surface_check_block_align(struct wined3d_surface *surface, const RECT *rect) DECLSPEC_HIDDEN; + + 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; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0074-wined3d-Get-rid-of-WINED3D_BUFFER_FLUSH.patch b/patches/wined3d-CSMT_Main/0074-wined3d-Get-rid-of-WINED3D_BUFFER_FLUSH.patch new file mode 100644 index 00000000..a74e0e6a --- /dev/null +++ b/patches/wined3d-CSMT_Main/0074-wined3d-Get-rid-of-WINED3D_BUFFER_FLUSH.patch @@ -0,0 +1,57 @@ +From 7a25ed307d8aa08209a3e56ad4aa0bfc5995a5f3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Tue, 7 May 2013 14:53:48 +0200 +Subject: wined3d: Get rid of WINED3D_BUFFER_FLUSH + +--- + dlls/wined3d/buffer.c | 13 +++++-------- + 1 file changed, 5 insertions(+), 8 deletions(-) + +diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c +index d2c1d62..5544640 100644 +--- a/dlls/wined3d/buffer.c ++++ b/dlls/wined3d/buffer.c +@@ -32,10 +32,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); + #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. */ +-#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 WINED3D_BUFFER_DISCARD 0x08 /* A DISCARD lock has occurred since the last preload. */ ++#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. */ + + #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 */ +@@ -167,8 +166,6 @@ static void buffer_create_buffer_object(struct wined3d_buffer *This, struct wine + { + 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)"); +- This->flags |= WINED3D_BUFFER_FLUSH; +- + 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; +@@ -707,7 +704,7 @@ static void buffer_direct_upload(struct wined3d_buffer *This, const struct wined + GL_EXTCALL(glFlushMappedBufferRange(This->buffer_type_hint, start, len)); + checkGLcall("glFlushMappedBufferRange"); + } +- else if (This->flags & WINED3D_BUFFER_FLUSH) ++ else if (This->flags & WINED3D_BUFFER_APPLESYNC) + { + GL_EXTCALL(glFlushMappedBufferRangeAPPLE(This->buffer_type_hint, start, len)); + checkGLcall("glFlushMappedBufferRangeAPPLE"); +@@ -1112,7 +1109,7 @@ void CDECL wined3d_buffer_unmap(struct wined3d_buffer *buffer) + checkGLcall("glFlushMappedBufferRange"); + } + } +- else if (buffer->flags & WINED3D_BUFFER_FLUSH) ++ else if (buffer->flags & WINED3D_BUFFER_APPLESYNC) + { + for (i = 0; i < buffer->modified_areas; ++i) + { +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0075-wined3d-Add-cs-waiting-debug-code.patch b/patches/wined3d-CSMT_Main/0075-wined3d-Add-cs-waiting-debug-code.patch new file mode 100644 index 00000000..e0295353 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0075-wined3d-Add-cs-waiting-debug-code.patch @@ -0,0 +1,29 @@ +From 121bee481f27a42d6a759a29a01b002ecffec65e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 4 Jul 2013 20:40:39 +0200 +Subject: wined3d: Add cs waiting debug code + +--- + dlls/wined3d/texture.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c +index 8212c96..b7891d9 100644 +--- a/dlls/wined3d/texture.c ++++ b/dlls/wined3d/texture.c +@@ -667,6 +667,12 @@ HRESULT CDECL wined3d_texture_set_color_key(struct wined3d_texture *texture, + return WINED3DERR_INVALIDCALL; + } + ++ if (wined3d_settings.cs_multithreaded) ++ { ++ FIXME("waiting for cs\n"); ++ texture->resource.device->cs->ops->finish(texture->resource.device->cs); ++ } ++ + if (color_key) + { + switch (flags & ~WINEDDCKEY_COLORSPACE) +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0076-wined3d-Don-t-force-strict-draw-ordering-for-multith.patch b/patches/wined3d-CSMT_Main/0076-wined3d-Don-t-force-strict-draw-ordering-for-multith.patch new file mode 100644 index 00000000..7fca25e5 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0076-wined3d-Don-t-force-strict-draw-ordering-for-multith.patch @@ -0,0 +1,26 @@ +From 6464090c8161886fba8637324b7714d67accf7c9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 4 Jul 2013 21:00:17 +0200 +Subject: wined3d: Don't force strict draw ordering for multithreaded CS + +Shouldn't be needed any more +--- + dlls/wined3d/wined3d_main.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/dlls/wined3d/wined3d_main.c b/dlls/wined3d/wined3d_main.c +index 5471e6e..e6dc444 100644 +--- a/dlls/wined3d/wined3d_main.c ++++ b/dlls/wined3d/wined3d_main.c +@@ -310,8 +310,6 @@ static BOOL wined3d_dll_init(HINSTANCE hInstDLL) + { + TRACE("Enabling multithreaded command stream.\n"); + wined3d_settings.cs_multithreaded = TRUE; +- TRACE("Enforcing strict draw ordering for multithreaded command stream.\n"); +- wined3d_settings.strict_draw_ordering = TRUE; + } + } + +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0077-wined3d-Send-render-target-view-clears-through-the-c.patch b/patches/wined3d-CSMT_Main/0077-wined3d-Send-render-target-view-clears-through-the-c.patch new file mode 100644 index 00000000..6fb7b854 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0077-wined3d-Send-render-target-view-clears-through-the-c.patch @@ -0,0 +1,118 @@ +From 793b7f174651b67263e170e1144b3c293eac651f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 4 Jul 2013 21:10:16 +0200 +Subject: wined3d: Send render target view clears through the command stream + +--- + dlls/wined3d/cs.c | 36 ++++++++++++++++++++++++++++++++++++ + dlls/wined3d/device.c | 12 ++---------- + dlls/wined3d/wined3d_private.h | 2 ++ + 3 files changed, 40 insertions(+), 10 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index dcaedfd..366a4d3 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -74,6 +74,7 @@ enum wined3d_cs_op + WINED3D_CS_OP_SET_LIGHT, + WINED3D_CS_OP_SET_LIGHT_ENABLE, + WINED3D_CS_OP_BLT, ++ WINED3D_CS_OP_CLEAR_RTV, + WINED3D_CS_OP_STOP, + }; + +@@ -343,6 +344,14 @@ struct wined3d_cs_blt + enum wined3d_texture_filter_type filter; + }; + ++struct wined3d_cs_clear_rtv ++{ ++ enum wined3d_cs_op opcode; ++ struct wined3d_rendertarget_view *view; ++ RECT rect; ++ struct wined3d_color color; ++}; ++ + /* FIXME: The list synchronization probably isn't particularly fast. */ + static void wined3d_cs_list_enqueue(struct wined3d_cs_list *list, struct wined3d_cs_block *block) + { +@@ -1652,6 +1661,32 @@ void wined3d_cs_emit_blt(struct wined3d_cs *cs, struct wined3d_surface *dst_surf + cs->ops->submit(cs); + } + ++static UINT wined3d_cs_exec_clear_rtv(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_clear_rtv *op = data; ++ struct wined3d_resource *resource = op->view->resource; ++ ++ resource = wined3d_texture_get_sub_resource(wined3d_texture_from_resource(resource), op->view->sub_resource_idx); ++ ++ surface_color_fill(surface_from_resource(resource), &op->rect, &op->color); ++ ++ return sizeof(*op); ++} ++ ++void wined3d_cs_emit_clear_rtv(struct wined3d_cs *cs, struct wined3d_rendertarget_view *view, ++ const RECT *rect, const struct wined3d_color *color) ++{ ++ struct wined3d_cs_clear_rtv *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_CLEAR_RTV; ++ op->view = view; ++ op->rect = *rect; ++ op->color = *color; ++ ++ cs->ops->submit(cs); ++} ++ + static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = + { + /* WINED3D_CS_OP_FENCE */ wined3d_cs_exec_fence, +@@ -1692,6 +1727,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* 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, + }; + + static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size) +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index 599a25d..b2e7ec3 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -3917,16 +3917,8 @@ HRESULT CDECL wined3d_device_clear_rendertarget_view(struct wined3d_device *devi + rect = &r; + } + +- if (wined3d_settings.cs_multithreaded) +- { +- FIXME("Waiting for cs.\n"); +- wined3d_cs_emit_glfinish(device->cs); +- device->cs->ops->finish(device->cs); +- } +- +- resource = wined3d_texture_get_sub_resource(wined3d_texture_from_resource(resource), view->sub_resource_idx); +- +- return surface_color_fill(surface_from_resource(resource), rect, color); ++ wined3d_cs_emit_clear_rtv(device->cs, view, rect, color); ++ return WINED3D_OK; + } + + struct wined3d_rendertarget_view * CDECL wined3d_device_get_rendertarget_view(const struct wined3d_device *device, +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 0d76377..e554099 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2638,6 +2638,8 @@ void wined3d_cs_emit_blt(struct wined3d_cs *cs, struct wined3d_surface *dst_surf + const RECT *dst_rect, struct wined3d_surface *src_surface, + const RECT *src_rect, DWORD flags, const WINEDDBLTFX *fx, + enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_clear_rtv(struct wined3d_cs *cs, struct wined3d_rendertarget_view *view, ++ const RECT *rect, const struct wined3d_color *color) DECLSPEC_HIDDEN; + + /* 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 +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0078-wined3d-Wait-for-the-CS-in-GetDC.patch b/patches/wined3d-CSMT_Main/0078-wined3d-Wait-for-the-CS-in-GetDC.patch new file mode 100644 index 00000000..6d2dc7c3 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0078-wined3d-Wait-for-the-CS-in-GetDC.patch @@ -0,0 +1,37 @@ +From 7cebca953dd9d2a81646a5277ff700e94cf401da Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 26 Sep 2013 16:40:34 +0200 +Subject: wined3d: Wait for the CS in GetDC. + +--- + dlls/wined3d/surface.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index c47f78c..9dadb6d 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -2478,6 +2478,20 @@ HRESULT CDECL wined3d_surface_getdc(struct wined3d_surface *surface, HDC *dc) + + TRACE("surface %p, dc %p.\n", surface, dc); + ++ if (!(surface->resource.format->flags & WINED3DFMT_FLAG_GETDC)) ++ { ++ WARN("Cannot use GetDC on a %s surface.\n", debug_d3dformat(surface->resource.format->id)); ++ return WINED3DERR_INVALIDCALL; ++ } ++ ++ if (wined3d_settings.cs_multithreaded) ++ { ++ struct wined3d_device *device = surface->resource.device; ++ FIXME("Waiting for cs.\n"); ++ wined3d_cs_emit_glfinish(device->cs); ++ device->cs->ops->finish(device->cs); ++ } ++ + /* Give more detailed info for ddraw. */ + if (surface->flags & SFLAG_DCINUSE) + return WINEDDERR_DCALREADYCREATED; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0079-wined3d-send-resource-maps-through-the-command-strea.patch b/patches/wined3d-CSMT_Main/0079-wined3d-send-resource-maps-through-the-command-strea.patch new file mode 100644 index 00000000..04398fac --- /dev/null +++ b/patches/wined3d-CSMT_Main/0079-wined3d-send-resource-maps-through-the-command-strea.patch @@ -0,0 +1,273 @@ +From aebae1f8597794f2fab4b468f2573a8591f60615 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 26 Sep 2013 16:41:00 +0200 +Subject: wined3d: send resource maps through the command stream + +Slow version only. Good enough to dodge some Nvidia bugs in the ddraw tests. +--- + dlls/wined3d/cs.c | 69 +++++++++++++++++++++++++++++++++++++ + dlls/wined3d/resource.c | 77 ++++++++++++++++++++++++------------------ + dlls/wined3d/wined3d_private.h | 5 +++ + 3 files changed, 119 insertions(+), 32 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 366a4d3..b691924 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -75,6 +75,8 @@ enum wined3d_cs_op + WINED3D_CS_OP_SET_LIGHT_ENABLE, + WINED3D_CS_OP_BLT, + WINED3D_CS_OP_CLEAR_RTV, ++ WINED3D_CS_OP_RESOURCE_MAP, ++ WINED3D_CS_OP_RESOURCE_UNMAP, + WINED3D_CS_OP_STOP, + }; + +@@ -352,6 +354,20 @@ struct wined3d_cs_clear_rtv + struct wined3d_color color; + }; + ++struct wined3d_cs_resource_map ++{ ++ enum wined3d_cs_op opcode; ++ struct wined3d_resource *resource; ++ DWORD flags; ++ void **mem; ++}; ++ ++struct wined3d_cs_resource_unmap ++{ ++ enum wined3d_cs_op opcode; ++ struct wined3d_resource *resource; ++}; ++ + /* FIXME: The list synchronization probably isn't particularly fast. */ + static void wined3d_cs_list_enqueue(struct wined3d_cs_list *list, struct wined3d_cs_block *block) + { +@@ -1687,6 +1703,57 @@ void wined3d_cs_emit_clear_rtv(struct wined3d_cs *cs, struct wined3d_rendertarge + cs->ops->submit(cs); + } + ++static UINT wined3d_cs_exec_resource_map(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_resource_map *op = data; ++ ++ *op->mem = wined3d_resource_map_internal(op->resource, op->flags); ++ ++ return sizeof(*op); ++} ++ ++void *wined3d_cs_emit_resource_map(struct wined3d_cs *cs, struct wined3d_resource *resource, ++ DWORD flags) ++{ ++ struct wined3d_cs_resource_map *op; ++ void *ret; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_RESOURCE_MAP; ++ op->resource = resource; ++ op->flags = flags; ++ op->mem = &ret; ++ ++ cs->ops->finish(cs); ++ ++ if (flags & (WINED3D_MAP_NOOVERWRITE | WINED3D_MAP_DISCARD)) ++ { ++ FIXME("Dynamic resource map is inefficient\n"); ++ } ++ return ret; ++} ++ ++static UINT wined3d_cs_exec_resource_unmap(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_resource_unmap *op = data; ++ struct wined3d_resource *resource = op->resource; ++ ++ wined3d_resource_unmap_internal(resource); ++ ++ return sizeof(*op); ++} ++ ++void wined3d_cs_emit_resource_unmap(struct wined3d_cs *cs, struct wined3d_resource *resource) ++{ ++ struct wined3d_cs_resource_unmap *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_RESOURCE_UNMAP; ++ op->resource = resource; ++ ++ cs->ops->submit(cs); ++} ++ + static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = + { + /* WINED3D_CS_OP_FENCE */ wined3d_cs_exec_fence, +@@ -1728,6 +1795,8 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* 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_MAP */ wined3d_cs_exec_resource_map, ++ /* WINED3D_CS_OP_RESOURCE_UNMAP */ wined3d_cs_exec_resource_unmap, + }; + + static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size) +diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c +index bf228d1..af60d51 100644 +--- a/dlls/wined3d/resource.c ++++ b/dlls/wined3d/resource.c +@@ -683,31 +683,11 @@ BOOL wined3d_resource_check_block_align(const struct wined3d_resource *resource, + return TRUE; + } + +-HRESULT wined3d_resource_map(struct wined3d_resource *resource, +- struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags) ++void *wined3d_resource_map_internal(struct wined3d_resource *resource, DWORD flags) + { + struct wined3d_device *device = resource->device; + struct wined3d_context *context = NULL; +- BYTE *base_memory; +- const struct wined3d_format *format = resource->format; +- +- TRACE("resource %p, map_desc %p, box %p, flags %#x.\n", +- resource, map_desc, box, flags); +- +- if (resource->map_count) +- { +- WARN("Volume is already mapped.\n"); +- return WINED3DERR_INVALIDCALL; +- } +- +- flags = wined3d_resource_sanitize_map_flags(resource, flags); +- +- if (wined3d_settings.cs_multithreaded) +- { +- FIXME("Waiting for cs.\n"); +- wined3d_cs_emit_glfinish(device->cs); +- device->cs->ops->finish(device->cs); +- } ++ void *mem; + + if (device->d3d_initialized) + context = context_acquire(device, NULL); +@@ -715,9 +695,8 @@ HRESULT wined3d_resource_map(struct wined3d_resource *resource, + if (!wined3d_resource_prepare_map_memory(resource, context)) + { + WARN("Out of memory.\n"); +- map_desc->data = NULL; + context_release(context); +- return E_OUTOFMEMORY; ++ return NULL; + } + + if (flags & WINED3D_MAP_DISCARD) +@@ -725,11 +704,39 @@ HRESULT wined3d_resource_map(struct wined3d_resource *resource, + else + wined3d_resource_load_location(resource, context, resource->map_binding); + +- base_memory = wined3d_resource_get_map_ptr(resource, context, flags); ++ mem = wined3d_resource_get_map_ptr(resource, context, flags); + + if (context) + context_release(context); + ++ return mem; ++} ++ ++HRESULT wined3d_resource_map(struct wined3d_resource *resource, ++ struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags) ++{ ++ struct wined3d_device *device = resource->device; ++ BYTE *base_memory; ++ const struct wined3d_format *format = resource->format; ++ ++ TRACE("resource %p, map_desc %p, box %p, flags %#x.\n", ++ resource, map_desc, box, flags); ++ ++ if (resource->map_count) ++ { ++ WARN("Volume is already mapped.\n"); ++ return WINED3DERR_INVALIDCALL; ++ } ++ ++ flags = wined3d_resource_sanitize_map_flags(resource, flags); ++ ++ base_memory = wined3d_cs_emit_resource_map(device->cs, resource, flags); ++ if (!base_memory) ++ { ++ WARN("Map failed.\n"); ++ return WINED3DERR_INVALIDCALL; ++ } ++ + TRACE("Base memory pointer %p.\n", base_memory); + + if (format->flags & WINED3DFMT_FLAG_BROKEN_PITCH) +@@ -781,10 +788,21 @@ HRESULT wined3d_resource_map(struct wined3d_resource *resource, + return WINED3D_OK; + } + +-HRESULT wined3d_resource_unmap(struct wined3d_resource *resource) ++void wined3d_resource_unmap_internal(struct wined3d_resource *resource) + { + struct wined3d_device *device = resource->device; + struct wined3d_context *context = NULL; ++ ++ if (device->d3d_initialized) ++ context = context_acquire(device, NULL); ++ wined3d_resource_release_map_ptr(resource, context); ++ if (context) ++ context_release(context); ++} ++ ++HRESULT wined3d_resource_unmap(struct wined3d_resource *resource) ++{ ++ struct wined3d_device *device = resource->device; + TRACE("resource %p.\n", resource); + + if (!resource->map_count) +@@ -793,12 +811,7 @@ HRESULT wined3d_resource_unmap(struct wined3d_resource *resource) + return WINEDDERR_NOTLOCKED; + } + +- if (device->d3d_initialized) +- context = context_acquire(device, NULL); +- wined3d_resource_release_map_ptr(resource, context); +- if (context) +- context_release(context); +- ++ wined3d_cs_emit_resource_unmap(device->cs, resource); + resource->map_count--; + + return WINED3D_OK; +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index e554099..6ee0c24 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2153,6 +2153,7 @@ void wined3d_resource_load_location(struct wined3d_resource *resource, + struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN; + HRESULT wined3d_resource_map(struct wined3d_resource *resource, struct wined3d_map_desc *map_desc, + const struct wined3d_box *box, DWORD flags) DECLSPEC_HIDDEN; ++void *wined3d_resource_map_internal(struct wined3d_resource *resource, DWORD flags) DECLSPEC_HIDDEN; + BOOL wined3d_resource_prepare_map_memory(struct wined3d_resource *resource, + struct wined3d_context *context) DECLSPEC_HIDDEN; + BOOL wined3d_resource_prepare_system_memory(struct wined3d_resource *resource) DECLSPEC_HIDDEN; +@@ -2160,6 +2161,7 @@ void wined3d_resource_release_map_ptr(const struct wined3d_resource *resource, + const struct wined3d_context *context) DECLSPEC_HIDDEN; + DWORD wined3d_resource_sanitize_map_flags(const struct wined3d_resource *resource, DWORD flags) DECLSPEC_HIDDEN; + HRESULT wined3d_resource_unmap(struct wined3d_resource *resource) DECLSPEC_HIDDEN; ++void wined3d_resource_unmap_internal(struct wined3d_resource *resource) DECLSPEC_HIDDEN; + void wined3d_resource_update_draw_binding(struct wined3d_resource *resource) DECLSPEC_HIDDEN; + void wined3d_resource_validate_location(struct wined3d_resource *resource, DWORD location) DECLSPEC_HIDDEN; + +@@ -2640,6 +2642,9 @@ void wined3d_cs_emit_blt(struct wined3d_cs *cs, struct wined3d_surface *dst_surf + enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN; + void wined3d_cs_emit_clear_rtv(struct wined3d_cs *cs, struct wined3d_rendertarget_view *view, + const RECT *rect, const struct wined3d_color *color) DECLSPEC_HIDDEN; ++void *wined3d_cs_emit_resource_map(struct wined3d_cs *cs, struct wined3d_resource *resource, ++ DWORD flags) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_resource_unmap(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN; + + /* 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 +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0080-wined3d-Get-rid-of-the-end_scene-flush-and-finish.patch b/patches/wined3d-CSMT_Main/0080-wined3d-Get-rid-of-the-end_scene-flush-and-finish.patch new file mode 100644 index 00000000..bb066e27 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0080-wined3d-Get-rid-of-the-end_scene-flush-and-finish.patch @@ -0,0 +1,45 @@ +From 907befb9104d166a5423d92c8aec0e8d6835bb92 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 4 Jul 2013 22:59:33 +0200 +Subject: wined3d: Get rid of the end_scene flush and finish + +Either keep the patch this way, or send a flush through the CS. I'm not +sure it's worth it though, this has never had any real performance +impact. +--- + dlls/wined3d/device.c | 12 ------------ + 1 file changed, 12 deletions(-) + +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index b2e7ec3..cd90c76 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -3224,8 +3224,6 @@ HRESULT CDECL wined3d_device_begin_scene(struct wined3d_device *device) + + HRESULT CDECL wined3d_device_end_scene(struct wined3d_device *device) + { +- struct wined3d_context *context; +- + TRACE("device %p.\n", device); + + if (!device->inScene) +@@ -3234,16 +3232,6 @@ HRESULT CDECL wined3d_device_end_scene(struct wined3d_device *device) + return WINED3DERR_INVALIDCALL; + } + +- context = context_acquire(device, NULL); +- /* We only have to do this if we need to read the, swapbuffers performs a flush for us */ +- if (wined3d_settings.cs_multithreaded) +- context->gl_info->gl_ops.gl.p_glFinish(); +- else +- context->gl_info->gl_ops.gl.p_glFlush(); +- /* No checkGLcall here to avoid locking the lock just for checking a call that hardly ever +- * fails. */ +- context_release(context); +- + device->inScene = FALSE; + return WINED3D_OK; + } +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0081-wined3d-Replace-the-linked-lists-with-a-ringbuffer.patch b/patches/wined3d-CSMT_Main/0081-wined3d-Replace-the-linked-lists-with-a-ringbuffer.patch new file mode 100644 index 00000000..add0b7fa --- /dev/null +++ b/patches/wined3d-CSMT_Main/0081-wined3d-Replace-the-linked-lists-with-a-ringbuffer.patch @@ -0,0 +1,843 @@ +From 68ab1f57ab88ea0592fcaa9c2c73a283fdb8dd3c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 4 Jul 2013 23:33:14 +0200 +Subject: wined3d: Replace the linked lists with a ringbuffer + +--- + dlls/wined3d/cs.c | 360 ++++++++++++++++++----------------------- + dlls/wined3d/wined3d_private.h | 20 +-- + 2 files changed, 161 insertions(+), 219 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index b691924..d35f114 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -22,20 +22,10 @@ + + WINE_DEFAULT_DEBUG_CHANNEL(d3d); + +-#define WINED3D_INITIAL_CS_SIZE 4096 +- +-static CRITICAL_SECTION wined3d_cs_list_mutex; +-static CRITICAL_SECTION_DEBUG wined3d_cs_list_mutex_debug = +-{ +- 0, 0, &wined3d_cs_list_mutex, +- {&wined3d_cs_list_mutex_debug.ProcessLocksList, +- &wined3d_cs_list_mutex_debug.ProcessLocksList}, +- 0, 0, {(DWORD_PTR)(__FILE__ ": wined3d_cs_list_mutex")} +-}; +-static CRITICAL_SECTION wined3d_cs_list_mutex = {&wined3d_cs_list_mutex_debug, -1, 0, 0, 0, 0}; +- + enum wined3d_cs_op + { ++ WINED3D_CS_OP_NOP, ++ WINED3D_CS_OP_SKIP, + WINED3D_CS_OP_FENCE, + WINED3D_CS_OP_PRESENT, + WINED3D_CS_OP_CLEAR, +@@ -368,99 +358,30 @@ struct wined3d_cs_resource_unmap + struct wined3d_resource *resource; + }; + +-/* FIXME: The list synchronization probably isn't particularly fast. */ +-static void wined3d_cs_list_enqueue(struct wined3d_cs_list *list, struct wined3d_cs_block *block) +-{ +- EnterCriticalSection(&wined3d_cs_list_mutex); +- list_add_tail(&list->blocks, &block->entry); +- LeaveCriticalSection(&wined3d_cs_list_mutex); +-} +- +-static struct wined3d_cs_block *wined3d_cs_list_dequeue(struct wined3d_cs_list *list) +-{ +- struct list *head; +- +- EnterCriticalSection(&wined3d_cs_list_mutex); +- if (!(head = list_head(&list->blocks))) +- { +- LeaveCriticalSection(&wined3d_cs_list_mutex); +- return NULL; +- } +- list_remove(head); +- LeaveCriticalSection(&wined3d_cs_list_mutex); +- +- return LIST_ENTRY(head, struct wined3d_cs_block, entry); +-} +- +-static struct wined3d_cs_block *wined3d_cs_list_dequeue_blocking(struct wined3d_cs_list *list) +-{ +- struct wined3d_cs_block *block; +- +- /* FIXME: Use an event to wait after a couple of spins. */ +- for (;;) +- { +- if ((block = wined3d_cs_list_dequeue(list))) +- return block; +- } +-} +- +-static void wined3d_cs_list_init(struct wined3d_cs_list *list) +-{ +- list_init(&list->blocks); +-} +- +-static struct wined3d_cs_block *wined3d_cs_get_thread_block(const struct wined3d_cs *cs) +-{ +- return TlsGetValue(cs->tls_idx); +-} +- +-static void wined3d_cs_set_thread_block(const struct wined3d_cs *cs, struct wined3d_cs_block *block) ++struct wined3d_cs_skip + { +- if (!TlsSetValue(cs->tls_idx, block)) +- ERR("Failed to set thread block.\n"); +-} ++ enum wined3d_cs_op opcode; ++ DWORD size; ++}; + +-static void wined3d_cs_flush(struct wined3d_cs *cs) ++static void wined3d_cs_submit(struct wined3d_cs *cs, size_t size) + { +- wined3d_cs_list_enqueue(&cs->exec_list, wined3d_cs_get_thread_block(cs)); +- wined3d_cs_set_thread_block(cs, NULL); ++ LONG new_val = (cs->queue.head + size) & (WINED3D_CS_QUEUE_SIZE - 1); ++ /* There is only one thread writing to queue.head, InterlockedExchange ++ * is used for the memory barrier. */ ++ InterlockedExchange(&cs->queue.head, new_val); + } + +-static struct wined3d_cs_block *wined3d_cs_get_block(struct wined3d_cs *cs) ++static UINT wined3d_cs_exec_nop(struct wined3d_cs *cs, const void *data) + { +- struct wined3d_cs_block *block; +- +- if (!(block = wined3d_cs_list_dequeue(&cs->free_list))) +- { +- if (!(block = HeapAlloc(GetProcessHeap(), 0, sizeof(*block)))) +- { +- ERR("Failed to get new block.\n"); +- return NULL; +- } +- } +- +- block->pos = 0; +- +- return block; ++ return sizeof(enum wined3d_cs_op); + } + +-static void *wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size) ++static UINT wined3d_cs_exec_skip(struct wined3d_cs *cs, const void *data) + { +- struct wined3d_cs_block *block = wined3d_cs_get_thread_block(cs); +- void *data; +- +- if (!block || block->pos + size > sizeof(block->data)) +- { +- if (block) +- wined3d_cs_flush(cs); +- block = wined3d_cs_get_block(cs); +- wined3d_cs_set_thread_block(cs, block); +- } ++ const struct wined3d_cs_skip *op = data; + +- data = &block->data[block->pos]; +- block->pos += size; +- +- return data; ++ return op->size; + } + + static UINT wined3d_cs_exec_fence(struct wined3d_cs *cs, const void *data) +@@ -481,14 +402,14 @@ static void wined3d_cs_emit_fence(struct wined3d_cs *cs, BOOL *signalled) + op = cs->ops->require_space(cs, sizeof(*op)); + op->opcode = WINED3D_CS_OP_FENCE; + op->signalled = signalled; ++ cs->ops->submit(cs, sizeof(*op)); + } + +-static void wined3d_cs_flush_and_wait(struct wined3d_cs *cs) ++static void wined3d_cs_finish(struct wined3d_cs *cs) + { + BOOL fence; + + wined3d_cs_emit_fence(cs, &fence); +- wined3d_cs_flush(cs); + + /* A busy wait should be fine, we're not supposed to have to wait very + * long. */ +@@ -546,7 +467,7 @@ void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *sw + + pending = InterlockedIncrement(&cs->pending_presents); + +- cs->ops->submit(cs); ++ cs->ops->submit(cs, sizeof(*op)); + + while (pending > 1) + pending = InterlockedCompareExchange(&cs->pending_presents, 0, 0); +@@ -573,8 +494,9 @@ void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT * + { + struct wined3d_cs_clear *op; + unsigned int extra_rects = rect_count ? rect_count - 1 : 0; ++ size_t size = sizeof(*op) + sizeof(*op->rects) * extra_rects; + +- op = cs->ops->require_space(cs, sizeof(*op) + sizeof(*op->rects) * extra_rects); ++ op = cs->ops->require_space(cs, size); + op->opcode = WINED3D_CS_OP_CLEAR; + op->rect_count = rect_count; + if (rect_count) +@@ -584,7 +506,7 @@ void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT * + op->depth = depth; + op->stencil = stencil; + +- cs->ops->submit(cs); ++ cs->ops->submit(cs, size); + } + + static UINT wined3d_cs_exec_draw(struct wined3d_cs *cs, const void *data) +@@ -625,7 +547,7 @@ void wined3d_cs_emit_draw(struct wined3d_cs *cs, UINT start_idx, UINT index_coun + op->instance_count = instance_count; + op->indexed = indexed; + +- cs->ops->submit(cs); ++ cs->ops->submit(cs, sizeof(*op)); + } + + static UINT wined3d_cs_exec_set_predication(struct wined3d_cs *cs, const void *data) +@@ -647,7 +569,7 @@ void wined3d_cs_emit_set_predication(struct wined3d_cs *cs, struct wined3d_query + op->predicate = predicate; + op->value = value; + +- cs->ops->submit(cs); ++ cs->ops->submit(cs, sizeof(*op)); + } + + static UINT wined3d_cs_exec_set_viewport(struct wined3d_cs *cs, const void *data) +@@ -669,7 +591,7 @@ void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_vi + op->opcode = WINED3D_CS_OP_SET_VIEWPORT; + op->viewport = *viewport; + +- cs->ops->submit(cs); ++ cs->ops->submit(cs, sizeof(*op)); + } + + static UINT wined3d_cs_exec_set_scissor_rect(struct wined3d_cs *cs, const void *data) +@@ -690,7 +612,7 @@ void wined3d_cs_emit_set_scissor_rect(struct wined3d_cs *cs, const RECT *rect) + op->opcode = WINED3D_CS_OP_SET_SCISSOR_RECT; + op->rect = *rect; + +- cs->ops->submit(cs); ++ cs->ops->submit(cs, sizeof(*op)); + } + + static UINT wined3d_cs_exec_set_rendertarget_view(struct wined3d_cs *cs, const void *data) +@@ -713,7 +635,7 @@ void wined3d_cs_emit_set_rendertarget_view(struct wined3d_cs *cs, unsigned int v + op->view_idx = view_idx; + op->view = view; + +- cs->ops->submit(cs); ++ cs->ops->submit(cs, sizeof(*op)); + } + + static UINT wined3d_cs_exec_set_depth_stencil_view(struct wined3d_cs *cs, const void *data) +@@ -766,7 +688,7 @@ void wined3d_cs_emit_set_depth_stencil_view(struct wined3d_cs *cs, struct wined3 + op->opcode = WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW; + op->view = view; + +- cs->ops->submit(cs); ++ cs->ops->submit(cs, sizeof(*op)); + } + + static UINT wined3d_cs_exec_set_vertex_declaration(struct wined3d_cs *cs, const void *data) +@@ -787,7 +709,7 @@ void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs, struct wined3 + op->opcode = WINED3D_CS_OP_SET_VERTEX_DECLARATION; + op->declaration = declaration; + +- cs->ops->submit(cs); ++ cs->ops->submit(cs, sizeof(*op)); + } + + static UINT wined3d_cs_exec_set_stream_source(struct wined3d_cs *cs, const void *data) +@@ -824,7 +746,7 @@ void wined3d_cs_emit_set_stream_source(struct wined3d_cs *cs, UINT stream_idx, + op->offset = offset; + op->stride = stride; + +- cs->ops->submit(cs); ++ cs->ops->submit(cs, sizeof(*op)); + } + + static UINT wined3d_cs_exec_set_stream_source_freq(struct wined3d_cs *cs, const void *data) +@@ -851,7 +773,7 @@ void wined3d_cs_emit_set_stream_source_freq(struct wined3d_cs *cs, UINT stream_i + op->frequency = frequency; + op->flags = flags; + +- cs->ops->submit(cs); ++ cs->ops->submit(cs, sizeof(*op)); + } + + static UINT wined3d_cs_exec_set_stream_output(struct wined3d_cs *cs, const void *data) +@@ -884,7 +806,7 @@ void wined3d_cs_emit_set_stream_output(struct wined3d_cs *cs, UINT stream_idx, + op->buffer = buffer; + op->offset = offset; + +- cs->ops->submit(cs); ++ cs->ops->submit(cs, sizeof(*op)); + } + + static UINT wined3d_cs_exec_set_index_buffer(struct wined3d_cs *cs, const void *data) +@@ -916,7 +838,7 @@ void wined3d_cs_emit_set_index_buffer(struct wined3d_cs *cs, struct wined3d_buff + op->buffer = buffer; + op->format_id = format_id; + +- cs->ops->submit(cs); ++ cs->ops->submit(cs, sizeof(*op)); + } + + static UINT wined3d_cs_exec_set_constant_buffer(struct wined3d_cs *cs, const void *data) +@@ -947,7 +869,7 @@ void wined3d_cs_emit_set_constant_buffer(struct wined3d_cs *cs, enum wined3d_sha + op->cb_idx = cb_idx; + op->buffer = buffer; + +- cs->ops->submit(cs); ++ cs->ops->submit(cs, sizeof(*op)); + } + + static UINT wined3d_cs_exec_set_texture(struct wined3d_cs *cs, const void *data) +@@ -1022,7 +944,7 @@ void wined3d_cs_emit_set_texture(struct wined3d_cs *cs, UINT stage, struct wined + op->opcode = WINED3D_CS_OP_SET_TEXTURE; + op->stage = stage; + op->texture = texture; +- cs->ops->submit(cs); ++ cs->ops->submit(cs, sizeof(*op)); + } + + static UINT wined3d_cs_exec_set_shader_resource_view(struct wined3d_cs *cs, const void *data) +@@ -1045,7 +967,7 @@ void wined3d_cs_emit_set_shader_resource_view(struct wined3d_cs *cs, enum wined3 + op->view_idx = view_idx; + op->view = view; + +- cs->ops->submit(cs); ++ cs->ops->submit(cs, sizeof(*op)); + } + + static UINT wined3d_cs_exec_set_sampler(struct wined3d_cs *cs, const void *data) +@@ -1068,7 +990,7 @@ void wined3d_cs_emit_set_sampler(struct wined3d_cs *cs, enum wined3d_shader_type + op->sampler_idx = sampler_idx; + op->sampler = sampler; + +- cs->ops->submit(cs); ++ cs->ops->submit(cs, sizeof(*op)); + } + + static UINT wined3d_cs_exec_set_shader(struct wined3d_cs *cs, const void *data) +@@ -1089,6 +1011,8 @@ void wined3d_cs_emit_set_shader(struct wined3d_cs *cs, enum wined3d_shader_type + op->opcode = WINED3D_CS_OP_SET_SHADER; + op->type = type; + op->shader = shader; ++ ++ cs->ops->submit(cs, sizeof(*op)); + } + + static UINT wined3d_cs_exec_set_vs_consts_f(struct wined3d_cs *cs, const void *data) +@@ -1124,8 +1048,9 @@ void wined3d_cs_emit_set_consts_f(struct wined3d_cs *cs, UINT start_register, + { + struct wined3d_cs_set_consts_f *op; + UINT extra_space = vector4f_count - 1; ++ size_t size = sizeof(*op) + sizeof(op->constants) * extra_space; + +- op = cs->ops->require_space(cs, sizeof(*op) + sizeof(op->constants) * extra_space); ++ op = cs->ops->require_space(cs, size); + switch (type) + { + case WINED3D_SHADER_TYPE_PIXEL: +@@ -1147,7 +1072,7 @@ void wined3d_cs_emit_set_consts_f(struct wined3d_cs *cs, UINT start_register, + op->vector4f_count = vector4f_count; + memcpy(op->constants, constants, sizeof(*constants) * 4 * vector4f_count); + +- cs->ops->submit(cs); ++ cs->ops->submit(cs, size); + } + + static UINT wined3d_cs_exec_set_render_state(struct wined3d_cs *cs, const void *data) +@@ -1169,8 +1094,8 @@ void wined3d_cs_emit_set_render_state(struct wined3d_cs *cs, enum wined3d_render + op->state = state; + op->value = value; + +- cs->ops->submit(cs); +-}; ++ cs->ops->submit(cs, sizeof(*op)); ++} + + static UINT wined3d_cs_exec_set_vs_consts_b(struct wined3d_cs *cs, const void *data) + { +@@ -1203,8 +1128,9 @@ void wined3d_cs_emit_set_consts_b(struct wined3d_cs *cs, UINT start_register, + { + struct wined3d_cs_set_consts_b *op; + UINT extra_space = bool_count - 1; ++ size_t size = sizeof(*op) + sizeof(op->constants) * extra_space; + +- op = cs->ops->require_space(cs, sizeof(*op) + sizeof(op->constants) * extra_space); ++ op = cs->ops->require_space(cs, size); + switch (type) + { + case WINED3D_SHADER_TYPE_PIXEL: +@@ -1226,7 +1152,7 @@ void wined3d_cs_emit_set_consts_b(struct wined3d_cs *cs, UINT start_register, + op->bool_count = bool_count; + memcpy(op->constants, constants, sizeof(op->constants) * bool_count); + +- cs->ops->submit(cs); ++ cs->ops->submit(cs, size); + } + + static UINT wined3d_cs_exec_set_vs_consts_i(struct wined3d_cs *cs, const void *data) +@@ -1260,8 +1186,9 @@ void wined3d_cs_emit_set_consts_i(struct wined3d_cs *cs, UINT start_register, + { + struct wined3d_cs_set_consts_i *op; + UINT extra_space = vector4i_count - 1; ++ size_t size = sizeof(*op) + sizeof(op->constants) * extra_space; + +- op = cs->ops->require_space(cs, sizeof(*op) + sizeof(op->constants) * extra_space); ++ op = cs->ops->require_space(cs, size); + switch (type) + { + case WINED3D_SHADER_TYPE_PIXEL: +@@ -1283,7 +1210,7 @@ void wined3d_cs_emit_set_consts_i(struct wined3d_cs *cs, UINT start_register, + op->vector4i_count = vector4i_count; + memcpy(op->constants, constants, sizeof(op->constants) * vector4i_count); + +- cs->ops->submit(cs); ++ cs->ops->submit(cs, size); + } + + static UINT wined3d_cs_exec_set_texture_state(struct wined3d_cs *cs, const void *data) +@@ -1307,7 +1234,7 @@ void wined3d_cs_emit_set_texture_state(struct wined3d_cs *cs, UINT stage, + op->state = state; + op->value = value; + +- cs->ops->submit(cs); ++ cs->ops->submit(cs, sizeof(*op)); + } + + static UINT wined3d_cs_exec_set_sampler_state(struct wined3d_cs *cs, const void *data) +@@ -1331,7 +1258,7 @@ void wined3d_cs_emit_set_sampler_state(struct wined3d_cs *cs, UINT sampler_idx, + op->state = state; + op->value = value; + +- cs->ops->submit(cs); ++ cs->ops->submit(cs, sizeof(*op)); + } + + static UINT wined3d_cs_exec_set_transform(struct wined3d_cs *cs, const void *data) +@@ -1355,7 +1282,7 @@ void wined3d_cs_emit_set_transform(struct wined3d_cs *cs, enum wined3d_transform + op->state = state; + op->matrix = *matrix; + +- cs->ops->submit(cs); ++ cs->ops->submit(cs, sizeof(*op)); + } + + static UINT wined3d_cs_exec_set_clip_plane(struct wined3d_cs *cs, const void *data) +@@ -1377,7 +1304,7 @@ void wined3d_cs_emit_set_clip_plane(struct wined3d_cs *cs, UINT plane_idx, const + op->plane_idx = plane_idx; + op->plane = *plane; + +- cs->ops->submit(cs); ++ cs->ops->submit(cs, sizeof(*op)); + } + + static UINT wined3d_cs_exec_set_material(struct wined3d_cs *cs, const void *data) +@@ -1398,7 +1325,7 @@ void wined3d_cs_emit_set_material(struct wined3d_cs *cs, const struct wined3d_ma + op->opcode = WINED3D_CS_OP_SET_MATERIAL; + op->material = *material; + +- cs->ops->submit(cs); ++ cs->ops->submit(cs, sizeof(*op)); + } + + static UINT wined3d_cs_exec_reset_state(struct wined3d_cs *cs, const void *data) +@@ -1422,7 +1349,7 @@ void wined3d_cs_emit_reset_state(struct wined3d_cs *cs) + op = cs->ops->require_space(cs, sizeof(*op)); + op->opcode = WINED3D_CS_OP_RESET_STATE; + +- cs->ops->submit(cs); ++ cs->ops->submit(cs, sizeof(*op)); + } + + static UINT wined3d_cs_exec_glfinish(struct wined3d_cs *cs, const void *data) +@@ -1448,7 +1375,7 @@ void wined3d_cs_emit_glfinish(struct wined3d_cs *cs) + op = cs->ops->require_space(cs, sizeof(*op)); + op->opcode = WINED3D_CS_OP_GLFINISH; + +- cs->ops->submit(cs); ++ cs->ops->submit(cs, sizeof(*op)); + } + + static UINT wined3d_cs_exec_set_base_vertex_index(struct wined3d_cs *cs, const void *data) +@@ -1470,7 +1397,7 @@ void wined3d_cs_emit_set_base_vertex_index(struct wined3d_cs *cs, + op->opcode = WINED3D_CS_OP_SET_BASE_VERTEX_INDEX; + op->base_vertex_index = base_vertex_index; + +- cs->ops->submit(cs); ++ cs->ops->submit(cs, sizeof(*op)); + } + + static UINT wined3d_cs_exec_set_primitive_type(struct wined3d_cs *cs, const void *data) +@@ -1496,7 +1423,7 @@ void wined3d_cs_emit_set_primitive_type(struct wined3d_cs *cs, GLenum primitive_ + op->opcode = WINED3D_CS_OP_SET_PRIMITIVE_TYPE; + op->gl_primitive_type = primitive_type; + +- cs->ops->submit(cs); ++ cs->ops->submit(cs, sizeof(*op)); + } + + static UINT wined3d_cs_exec_set_light(struct wined3d_cs *cs, const void *data) +@@ -1553,7 +1480,7 @@ void wined3d_cs_emit_set_light(struct wined3d_cs *cs, const struct wined3d_light + op->opcode = WINED3D_CS_OP_SET_LIGHT; + op->light = *light; + +- cs->ops->submit(cs); ++ cs->ops->submit(cs, sizeof(*op)); + } + + static UINT wined3d_cs_exec_set_light_enable(struct wined3d_cs *cs, const void *data) +@@ -1642,7 +1569,7 @@ void wined3d_cs_emit_set_light_enable(struct wined3d_cs *cs, UINT idx, BOOL enab + op->idx = idx; + op->enable = enable; + +- cs->ops->submit(cs); ++ cs->ops->submit(cs, sizeof(*op)); + } + + static UINT wined3d_cs_exec_blt(struct wined3d_cs *cs, const void *data) +@@ -1674,7 +1601,7 @@ void wined3d_cs_emit_blt(struct wined3d_cs *cs, struct wined3d_surface *dst_surf + if (fx) + op->fx = *fx; + +- cs->ops->submit(cs); ++ cs->ops->submit(cs, sizeof(*op)); + } + + static UINT wined3d_cs_exec_clear_rtv(struct wined3d_cs *cs, const void *data) +@@ -1700,7 +1627,7 @@ void wined3d_cs_emit_clear_rtv(struct wined3d_cs *cs, struct wined3d_rendertarge + op->rect = *rect; + op->color = *color; + +- cs->ops->submit(cs); ++ cs->ops->submit(cs, sizeof(*op)); + } + + static UINT wined3d_cs_exec_resource_map(struct wined3d_cs *cs, const void *data) +@@ -1724,12 +1651,14 @@ void *wined3d_cs_emit_resource_map(struct wined3d_cs *cs, struct wined3d_resourc + op->flags = flags; + op->mem = &ret; + +- cs->ops->finish(cs); ++ cs->ops->submit(cs, sizeof(*op)); + + if (flags & (WINED3D_MAP_NOOVERWRITE | WINED3D_MAP_DISCARD)) + { + FIXME("Dynamic resource map is inefficient\n"); + } ++ cs->ops->finish(cs); ++ + return ret; + } + +@@ -1751,11 +1680,13 @@ void wined3d_cs_emit_resource_unmap(struct wined3d_cs *cs, struct wined3d_resour + op->opcode = WINED3D_CS_OP_RESOURCE_UNMAP; + op->resource = resource; + +- cs->ops->submit(cs); ++ cs->ops->submit(cs, sizeof(*op)); + } + + static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = + { ++ /* 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, +@@ -1799,42 +1730,59 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* WINED3D_CS_OP_RESOURCE_UNMAP */ wined3d_cs_exec_resource_unmap, + }; + +-static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size) ++static void *wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size) + { +- if (size > cs->data_size) ++ struct wined3d_cs_queue *queue = &cs->queue; ++ size_t queue_size = sizeof(queue->data) / sizeof(*queue->data); ++ ++ if (queue_size - size < queue->head) + { +- void *new_data; ++ struct wined3d_cs_skip *skip; ++ size_t nop_size = queue_size - queue->head; + +- size = max( size, cs->data_size * 2 ); +- if (!(new_data = HeapReAlloc(GetProcessHeap(), 0, cs->data, size))) +- return NULL; ++ skip = wined3d_cs_mt_require_space(cs, nop_size); ++ if (nop_size < sizeof(*skip)) ++ { ++ skip->opcode = WINED3D_CS_OP_NOP; ++ } ++ else ++ { ++ skip->opcode = WINED3D_CS_OP_SKIP; ++ skip->size = nop_size; ++ } + +- cs->data_size = size; +- cs->data = new_data; ++ cs->ops->submit(cs, nop_size); ++ assert(!queue->head); + } + +- return cs->data; +-} ++ 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; + +-static void wined3d_cs_st_submit(struct wined3d_cs *cs) +-{ +- enum wined3d_cs_op opcode = *(const enum wined3d_cs_op *)cs->data; ++ TRACE("Waiting for free space. Head %u, tail %u, want %u\n", head, tail, ++ (unsigned int) size); ++ } + +- wined3d_cs_op_handlers[opcode](cs, cs->data); ++ return &queue->data[queue->head]; + } + +-static const struct wined3d_cs_ops wined3d_cs_st_ops = +-{ +- wined3d_cs_st_require_space, +- wined3d_cs_st_submit, +- wined3d_cs_st_submit, +-}; +- + static const struct wined3d_cs_ops wined3d_cs_mt_ops = + { + wined3d_cs_mt_require_space, +- wined3d_cs_flush, +- wined3d_cs_flush_and_wait, ++ wined3d_cs_submit, ++ wined3d_cs_finish, + }; + + /* FIXME: wined3d_device_uninit_3d() should either flush and wait, or be an +@@ -1846,9 +1794,38 @@ static void wined3d_cs_emit_stop(struct wined3d_cs *cs) + op = wined3d_cs_mt_require_space(cs, sizeof(*op)); + op->opcode = WINED3D_CS_OP_STOP; + +- wined3d_cs_flush(cs); ++ wined3d_cs_submit(cs, sizeof(*op)); ++} ++ ++static void wined3d_cs_st_submit(struct wined3d_cs *cs, size_t size) ++{ ++ enum wined3d_cs_op opcode = *(const enum wined3d_cs_op *)&cs->queue.data; ++ ++ if (opcode >= WINED3D_CS_OP_STOP) ++ { ++ ERR("Invalid opcode %#x.\n", opcode); ++ return; ++ } ++ ++ wined3d_cs_op_handlers[opcode](cs, &cs->queue.data); + } + ++static void wined3d_cs_st_finish(struct wined3d_cs *cs) ++{ ++} ++ ++static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size) ++{ ++ return cs->queue.data; ++} ++ ++static const struct wined3d_cs_ops wined3d_cs_st_ops = ++{ ++ wined3d_cs_st_require_space, ++ wined3d_cs_st_submit, ++ wined3d_cs_st_finish, ++}; ++ + void wined3d_cs_switch_onscreen_ds(struct wined3d_cs *cs, + struct wined3d_context *context, struct wined3d_surface *depth_stencil) + { +@@ -1868,31 +1845,32 @@ void wined3d_cs_switch_onscreen_ds(struct wined3d_cs *cs, + static DWORD WINAPI wined3d_cs_run(void *thread_param) + { + struct wined3d_cs *cs = thread_param; ++ enum wined3d_cs_op opcode; ++ LONG tail; + + TRACE("Started.\n"); + + cs->thread_id = GetCurrentThreadId(); + for (;;) + { +- struct wined3d_cs_block *block; +- UINT pos = 0; +- +- block = wined3d_cs_list_dequeue_blocking(&cs->exec_list); +- while (pos < block->pos) ++ if (*((volatile LONG *)&cs->queue.head) == cs->queue.tail) + { +- enum wined3d_cs_op opcode = *(const enum wined3d_cs_op *)&block->data[pos]; ++ continue; ++ } + +- if (opcode >= WINED3D_CS_OP_STOP) +- { +- if (opcode > WINED3D_CS_OP_STOP) +- ERR("Invalid opcode %#x.\n", opcode); +- goto done; +- } ++ tail = cs->queue.tail; ++ opcode = *(const enum wined3d_cs_op *)&cs->queue.data[tail]; + +- pos += wined3d_cs_op_handlers[opcode](cs, &block->data[pos]); ++ if (opcode >= WINED3D_CS_OP_STOP) ++ { ++ if (opcode > WINED3D_CS_OP_STOP) ++ ERR("Invalid opcode %#x.\n", opcode); ++ goto done; + } + +- wined3d_cs_list_enqueue(&cs->free_list, block); ++ tail += wined3d_cs_op_handlers[opcode](cs, &cs->queue.data[tail]); ++ tail &= (WINED3D_CS_QUEUE_SIZE - 1); ++ InterlockedExchange(&cs->queue.tail, tail); + } + + done: +@@ -1917,25 +1895,10 @@ struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device) + 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))) +- { +- goto err; +- } +- +- if ((cs->tls_idx = TlsAlloc()) == TLS_OUT_OF_INDEXES) +- { +- ERR("Failed to allocate cs TLS index, err %#x.\n", GetLastError()); +- goto err; +- } +- + if (wined3d_settings.cs_multithreaded) + { + cs->ops = &wined3d_cs_mt_ops; + +- wined3d_cs_list_init(&cs->free_list); +- wined3d_cs_list_init(&cs->exec_list); +- + if (!(cs->thread = CreateThread(NULL, 0, wined3d_cs_run, cs, 0, NULL))) + { + ERR("Failed to create wined3d command stream thread.\n"); +@@ -1947,12 +1910,7 @@ struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device) + + err: + if (cs) +- { + state_cleanup(&cs->state); +- if (cs->tls_idx != TLS_OUT_OF_INDEXES && !TlsFree(cs->tls_idx)) +- ERR("Failed to free cs TLS index, err %#x.\n", GetLastError()); +- HeapFree(GetProcessHeap(), 0, cs->data); +- } + HeapFree(GetProcessHeap(), 0, cs); + return NULL; + } +@@ -1971,17 +1929,7 @@ void wined3d_cs_destroy(struct wined3d_cs *cs) + CloseHandle(cs->thread); + if (ret != WAIT_OBJECT_0) + ERR("Wait failed (%#x).\n", ret); +- +- /* FIXME: Cleanup the block lists on thread exit. */ +-#if 0 +- wined3d_cs_list_cleanup(&cs->exec_list); +- wined3d_cs_list_cleanup(&cs->free_list); +-#endif + } + +- if (!TlsFree(cs->tls_idx)) +- ERR("Failed to free cs TLS index, err %#x.\n", GetLastError()); +- +- HeapFree(GetProcessHeap(), 0, cs->data); + HeapFree(GetProcessHeap(), 0, cs); + } +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 6ee0c24..59d9753 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -31,6 +31,7 @@ + #define WINE_GLAPI + #endif + ++#include + #include + #include + #include +@@ -2537,19 +2538,17 @@ struct wined3d_cs_list + struct list blocks; + }; + +-struct wined3d_cs_block ++#define WINED3D_CS_QUEUE_SIZE 0x100000 ++struct wined3d_cs_queue + { +- struct list entry; +- UINT pos; +- /* FIXME? The size is somewhat arbitrary. It's big enough for huge +- * shader constant set calls though */ +- BYTE data[sizeof(float) * 4 * 256 * 2]; ++ LONG head, tail; ++ BYTE data[WINED3D_CS_QUEUE_SIZE]; + }; + + struct wined3d_cs_ops + { + void *(*require_space)(struct wined3d_cs *cs, size_t size); +- void (*submit)(struct wined3d_cs *cs); ++ void (*submit)(struct wined3d_cs *cs, size_t size); + void (*finish)(struct wined3d_cs *cs); + }; + +@@ -2560,14 +2559,9 @@ struct wined3d_cs + struct wined3d_state state; + HANDLE thread; + DWORD thread_id; +- DWORD tls_idx; + struct wined3d_surface *onscreen_depth_stencil; + +- size_t data_size; +- void *data; +- +- struct wined3d_cs_list free_list; +- struct wined3d_cs_list exec_list; ++ struct wined3d_cs_queue queue; + + LONG pending_presents; + }; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0082-wined3d-Don-t-preload-buffers-on-unmap.patch b/patches/wined3d-CSMT_Main/0082-wined3d-Don-t-preload-buffers-on-unmap.patch new file mode 100644 index 00000000..9962f2d6 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0082-wined3d-Don-t-preload-buffers-on-unmap.patch @@ -0,0 +1,27 @@ +From 0603f71135885ebf0666d406380385936ed5ff7b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 4 Jul 2013 23:40:56 +0200 +Subject: wined3d: Don't preload buffers on unmap + +--- + dlls/wined3d/buffer.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c +index 5544640..b76a07d 100644 +--- a/dlls/wined3d/buffer.c ++++ b/dlls/wined3d/buffer.c +@@ -1129,10 +1129,6 @@ void CDECL wined3d_buffer_unmap(struct wined3d_buffer *buffer) + buffer_clear_dirty_areas(buffer); + buffer->map_ptr = NULL; + } +- else if (buffer->flags & WINED3D_BUFFER_HASDESC) +- { +- wined3d_buffer_preload(buffer); +- } + } + + static ULONG buffer_resource_incref(struct wined3d_resource *resource) +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0083-wined3d-Don-t-call-glFinish-before-swapping.patch b/patches/wined3d-CSMT_Main/0083-wined3d-Don-t-call-glFinish-before-swapping.patch new file mode 100644 index 00000000..ca3fe4fa --- /dev/null +++ b/patches/wined3d-CSMT_Main/0083-wined3d-Don-t-call-glFinish-before-swapping.patch @@ -0,0 +1,29 @@ +From 808198079459086ac70236bacaacd85aa717f7ff Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 4 Jul 2013 23:50:20 +0200 +Subject: wined3d: Don't call glFinish before swapping + +The code is probably not ready yet, so delay this patch until everything +is CSified. Right now I need it for performance testing. +--- + dlls/wined3d/swapchain.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c +index fa0c241..7ebdd1b 100644 +--- a/dlls/wined3d/swapchain.c ++++ b/dlls/wined3d/swapchain.c +@@ -531,9 +531,7 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT + swapchain_blit(swapchain, context, &src_rect, &dst_rect); + } + +- if (wined3d_settings.cs_multithreaded) +- gl_info->gl_ops.gl.p_glFinish(); +- else if (swapchain->num_contexts > 1) ++ if (swapchain->num_contexts > 1 && !wined3d_settings.cs_multithreaded) + gl_info->gl_ops.gl.p_glFlush(); + + /* call wglSwapBuffers through the gl table to avoid confusing the Steam overlay */ +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0084-wined3d-wined3d_-_query_issue-never-fails.patch b/patches/wined3d-CSMT_Main/0084-wined3d-wined3d_-_query_issue-never-fails.patch new file mode 100644 index 00000000..83a213a4 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0084-wined3d-wined3d_-_query_issue-never-fails.patch @@ -0,0 +1,116 @@ +From ea0804eca5b9d5df9eeb4a435d11ad1e6f4227b1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Sat, 6 Jul 2013 18:15:00 +0200 +Subject: wined3d: wined3d_*_query_issue never fails + +--- + dlls/wined3d/query.c | 21 ++++++++------------- + dlls/wined3d/wined3d_private.h | 2 +- + 2 files changed, 9 insertions(+), 14 deletions(-) + +diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c +index e755764..3de4282 100644 +--- a/dlls/wined3d/query.c ++++ b/dlls/wined3d/query.c +@@ -292,7 +292,8 @@ HRESULT CDECL wined3d_query_issue(struct wined3d_query *query, DWORD flags) + { + TRACE("query %p, flags %#x.\n", query, flags); + +- return query->query_ops->query_issue(query, flags); ++ query->query_ops->query_issue(query, flags); ++ return WINED3D_OK; + } + + static void fill_query_data(void *out, unsigned int out_size, const void *result, unsigned int result_size) +@@ -435,7 +436,7 @@ enum wined3d_query_type CDECL wined3d_query_get_type(const struct wined3d_query + return query->type; + } + +-static HRESULT wined3d_event_query_ops_issue(struct wined3d_query *query, DWORD flags) ++static void wined3d_event_query_ops_issue(struct wined3d_query *query, DWORD flags) + { + TRACE("query %p, flags %#x.\n", query, flags); + +@@ -445,7 +446,7 @@ static HRESULT wined3d_event_query_ops_issue(struct wined3d_query *query, DWORD + struct wined3d_event_query *event_query = query->extendedData; + + /* Faked event query support */ +- if (!event_query) return WINED3D_OK; ++ if (!event_query) return; + + wined3d_event_query_issue(event_query, query->device); + } +@@ -459,11 +460,9 @@ static HRESULT wined3d_event_query_ops_issue(struct wined3d_query *query, DWORD + 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) ++static void 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; +@@ -542,7 +541,7 @@ static HRESULT wined3d_occlusion_query_ops_issue(struct wined3d_query *query, DW + else + query->state = QUERY_SIGNALLED; + +- return WINED3D_OK; /* can be WINED3DERR_INVALIDCALL. */ ++ return; + } + + static HRESULT wined3d_timestamp_query_ops_get_data(struct wined3d_query *query, +@@ -605,7 +604,7 @@ static HRESULT wined3d_timestamp_query_ops_get_data(struct wined3d_query *query, + return res; + } + +-static HRESULT wined3d_timestamp_query_ops_issue(struct wined3d_query *query, DWORD flags) ++static void wined3d_timestamp_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; +@@ -639,8 +638,6 @@ static HRESULT wined3d_timestamp_query_ops_issue(struct wined3d_query *query, DW + + if (flags & WINED3DISSUE_END) + query->state = QUERY_SIGNALLED; +- +- return WINED3D_OK; + } + + static HRESULT wined3d_timestamp_disjoint_query_ops_get_data(struct wined3d_query *query, +@@ -669,7 +666,7 @@ static HRESULT wined3d_timestamp_disjoint_query_ops_get_data(struct wined3d_quer + return S_OK; + } + +-static HRESULT wined3d_timestamp_disjoint_query_ops_issue(struct wined3d_query *query, DWORD flags) ++static void wined3d_timestamp_disjoint_query_ops_issue(struct wined3d_query *query, DWORD flags) + { + TRACE("query %p, flags %#x.\n", query, flags); + +@@ -677,8 +674,6 @@ static HRESULT wined3d_timestamp_disjoint_query_ops_issue(struct wined3d_query * + query->state = QUERY_BUILDING; + if (flags & WINED3DISSUE_END) + query->state = QUERY_SIGNALLED; +- +- return WINED3D_OK; + } + + static const struct wined3d_query_ops event_query_ops = +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 59d9753..ff05a97 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2653,7 +2653,7 @@ enum query_state { + struct wined3d_query_ops + { + HRESULT (*query_get_data)(struct wined3d_query *query, void *data, DWORD data_size, DWORD flags); +- HRESULT (*query_issue)(struct wined3d_query *query, DWORD flags); ++ void (*query_issue)(struct wined3d_query *query, DWORD flags); + }; + + struct wined3d_query +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0085-wined3d-Add-query-support-to-the-command-stream.patch b/patches/wined3d-CSMT_Main/0085-wined3d-Add-query-support-to-the-command-stream.patch new file mode 100644 index 00000000..da480e99 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0085-wined3d-Add-query-support-to-the-command-stream.patch @@ -0,0 +1,163 @@ +From c0687b2ce9d0056bce2fc514f25baa20ab834f1e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Sat, 6 Jul 2013 18:26:11 +0200 +Subject: wined3d: Add query support to the command stream + +--- + dlls/wined3d/cs.c | 73 ++++++++++++++++++++++++++++++++++++++++++ + dlls/wined3d/query.c | 8 +++-- + dlls/wined3d/wined3d_private.h | 4 +++ + 3 files changed, 83 insertions(+), 2 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index d35f114..e4d60d8 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -67,6 +67,8 @@ enum wined3d_cs_op + WINED3D_CS_OP_CLEAR_RTV, + WINED3D_CS_OP_RESOURCE_MAP, + WINED3D_CS_OP_RESOURCE_UNMAP, ++ WINED3D_CS_OP_QUERY_ISSUE, ++ WINED3D_CS_OP_QUERY_GET_DATA, + WINED3D_CS_OP_STOP, + }; + +@@ -364,6 +366,23 @@ struct wined3d_cs_skip + DWORD size; + }; + ++struct wined3d_cs_query_issue ++{ ++ enum wined3d_cs_op opcode; ++ struct wined3d_query *query; ++ DWORD flags; ++}; ++ ++struct wined3d_cs_query_get_data ++{ ++ enum wined3d_cs_op opcode; ++ struct wined3d_query *query; ++ void *data; ++ UINT data_size; ++ DWORD flags; ++ HRESULT *ret; ++}; ++ + static void wined3d_cs_submit(struct wined3d_cs *cs, size_t size) + { + LONG new_val = (cs->queue.head + size) & (WINED3D_CS_QUEUE_SIZE - 1); +@@ -1683,6 +1702,58 @@ void wined3d_cs_emit_resource_unmap(struct wined3d_cs *cs, struct wined3d_resour + cs->ops->submit(cs, sizeof(*op)); + } + ++static UINT wined3d_cs_exec_query_issue(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_query_issue *op = data; ++ ++ op->query->query_ops->query_issue(op->query, op->flags); ++ ++ return sizeof(*op); ++} ++ ++void wined3d_cs_emit_query_issue(struct wined3d_cs *cs, struct wined3d_query *query, DWORD flags) ++{ ++ struct wined3d_cs_query_issue *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_QUERY_ISSUE; ++ op->query = query; ++ op->flags = flags; ++ ++ cs->ops->submit(cs, sizeof(*op)); ++} ++ ++static UINT wined3d_cs_exec_query_get_data(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_query_get_data *op = data; ++ struct wined3d_query *query = op->query; ++ ++ *op->ret = query->query_ops->query_get_data(query, op->data, op->data_size, op->flags); ++ ++ return sizeof(*op); ++} ++ ++void wined3d_cs_emit_query_get_data(struct wined3d_cs *cs, struct wined3d_query *query, void *data, ++ UINT data_size, DWORD flags, HRESULT *ret) ++{ ++ struct wined3d_cs_query_get_data *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_QUERY_GET_DATA; ++ op->query = query; ++ op->data = data; ++ op->data_size = data_size; ++ op->flags = flags; ++ op->ret = ret; ++ ++ cs->ops->submit(cs, sizeof(*op)); ++ ++ if (wined3d_settings.cs_multithreaded) ++ FIXME("Query handling is not particularly fast yet\n"); ++ ++ cs->ops->finish(cs); ++} ++ + static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = + { + /* WINED3D_CS_OP_NOP */ wined3d_cs_exec_nop, +@@ -1728,6 +1799,8 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* WINED3D_CS_OP_CLEAR_RTV */ wined3d_cs_exec_clear_rtv, + /* WINED3D_CS_OP_RESOURCE_MAP */ wined3d_cs_exec_resource_map, + /* WINED3D_CS_OP_RESOURCE_UNMAP */ wined3d_cs_exec_resource_unmap, ++ /* WINED3D_CS_OP_QUERY_ISSUE */ wined3d_cs_exec_query_issue, ++ /* WINED3D_CS_OP_QUERY_GET_DATA */ wined3d_cs_exec_query_get_data, + }; + + static void *wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size) +diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c +index 3de4282..6436bd7 100644 +--- a/dlls/wined3d/query.c ++++ b/dlls/wined3d/query.c +@@ -275,10 +275,14 @@ ULONG CDECL wined3d_query_decref(struct wined3d_query *query) + HRESULT CDECL wined3d_query_get_data(struct wined3d_query *query, + void *data, UINT data_size, DWORD flags) + { ++ HRESULT hr; + TRACE("query %p, data %p, data_size %u, flags %#x.\n", + query, data, data_size, flags); + +- return query->query_ops->query_get_data(query, data, data_size, flags); ++ wined3d_cs_emit_query_get_data(query->device->cs, query, data, data_size, ++ flags, &hr); ++ ++ return hr; + } + + UINT CDECL wined3d_query_get_data_size(const struct wined3d_query *query) +@@ -292,7 +296,7 @@ HRESULT CDECL wined3d_query_issue(struct wined3d_query *query, DWORD flags) + { + TRACE("query %p, flags %#x.\n", query, flags); + +- query->query_ops->query_issue(query, flags); ++ wined3d_cs_emit_query_issue(query->device->cs, query, flags); + return WINED3D_OK; + } + +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index ff05a97..6175f13 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2639,6 +2639,10 @@ void wined3d_cs_emit_clear_rtv(struct wined3d_cs *cs, struct wined3d_rendertarge + void *wined3d_cs_emit_resource_map(struct wined3d_cs *cs, struct wined3d_resource *resource, + DWORD flags) DECLSPEC_HIDDEN; + void wined3d_cs_emit_resource_unmap(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_query_issue(struct wined3d_cs *cs, struct wined3d_query *query, ++ DWORD flags) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_query_get_data(struct wined3d_cs *cs, struct wined3d_query *query, void *data, ++ UINT data_size, DWORD flags, HRESULT *ret) DECLSPEC_HIDDEN; + + /* 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 +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0086-wined3d-Check-our-CS-state-to-find-out-if-a-query-is.patch b/patches/wined3d-CSMT_Main/0086-wined3d-Check-our-CS-state-to-find-out-if-a-query-is.patch new file mode 100644 index 00000000..0c045f04 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0086-wined3d-Check-our-CS-state-to-find-out-if-a-query-is.patch @@ -0,0 +1,72 @@ +From ed3e1f3c0fb3ed7d687235e0683039169d412c99 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Sat, 6 Jul 2013 18:31:41 +0200 +Subject: wined3d: Check our CS state to find out if a query is done + +--- + dlls/wined3d/cs.c | 6 +++++- + dlls/wined3d/query.c | 9 +++++++++ + dlls/wined3d/wined3d_private.h | 2 ++ + 3 files changed, 16 insertions(+), 1 deletion(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index e4d60d8..ba8e840 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -1705,8 +1705,12 @@ void wined3d_cs_emit_resource_unmap(struct wined3d_cs *cs, struct wined3d_resour + static UINT wined3d_cs_exec_query_issue(struct wined3d_cs *cs, const void *data) + { + const struct wined3d_cs_query_issue *op = data; ++ struct wined3d_query *query = op->query; ++ ++ query->query_ops->query_issue(query, op->flags); + +- op->query->query_ops->query_issue(op->query, op->flags); ++ if (op->flags & WINED3DISSUE_END) ++ InterlockedIncrement(&query->counter_worker); + + return sizeof(*op); + } +diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c +index 6436bd7..bea03ed 100644 +--- a/dlls/wined3d/query.c ++++ b/dlls/wined3d/query.c +@@ -279,6 +279,12 @@ HRESULT CDECL wined3d_query_get_data(struct wined3d_query *query, + TRACE("query %p, data %p, data_size %u, flags %#x.\n", + query, data, data_size, flags); + ++ if (query->counter_main != query->counter_worker) ++ { ++ TRACE("D3DISSUE_END command not submitted to GL yet\n"); ++ return S_FALSE; ++ } ++ + wined3d_cs_emit_query_get_data(query->device->cs, query, data, data_size, + flags, &hr); + +@@ -296,6 +302,9 @@ HRESULT CDECL wined3d_query_issue(struct wined3d_query *query, DWORD flags) + { + TRACE("query %p, flags %#x.\n", query, flags); + ++ if (flags & WINED3DISSUE_END) ++ query->counter_main++; ++ + wined3d_cs_emit_query_issue(query->device->cs, query, flags); + return WINED3D_OK; + } +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 6175f13..3fd7fa7 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2671,6 +2671,8 @@ struct wined3d_query + enum wined3d_query_type type; + DWORD data_size; + void *extendedData; ++ ++ LONG counter_main, counter_worker; + }; + + /* TODO: Add tests and support for FLOAT16_4 POSITIONT, D3DCOLOR position, other +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0087-wined3d-Poll-queries-automatically-in-the-CS.patch b/patches/wined3d-CSMT_Main/0087-wined3d-Poll-queries-automatically-in-the-CS.patch new file mode 100644 index 00000000..faf6dfc4 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0087-wined3d-Poll-queries-automatically-in-the-CS.patch @@ -0,0 +1,586 @@ +From e041aaa221e23ed7af4d1620180dc4e00cf006f3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Sat, 6 Jul 2013 19:18:48 +0200 +Subject: wined3d: Poll queries automatically in the CS + +--- + dlls/wined3d/cs.c | 76 ++++++-------- + dlls/wined3d/query.c | 225 ++++++++++++++++++++++++++--------------- + dlls/wined3d/wined3d_private.h | 7 +- + 3 files changed, 180 insertions(+), 128 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index ba8e840..68e1ed7 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -68,7 +68,6 @@ enum wined3d_cs_op + WINED3D_CS_OP_RESOURCE_MAP, + WINED3D_CS_OP_RESOURCE_UNMAP, + WINED3D_CS_OP_QUERY_ISSUE, +- WINED3D_CS_OP_QUERY_GET_DATA, + WINED3D_CS_OP_STOP, + }; + +@@ -373,16 +372,6 @@ struct wined3d_cs_query_issue + DWORD flags; + }; + +-struct wined3d_cs_query_get_data +-{ +- enum wined3d_cs_op opcode; +- struct wined3d_query *query; +- void *data; +- UINT data_size; +- DWORD flags; +- HRESULT *ret; +-}; +- + static void wined3d_cs_submit(struct wined3d_cs *cs, size_t size) + { + LONG new_val = (cs->queue.head + size) & (WINED3D_CS_QUEUE_SIZE - 1); +@@ -1709,8 +1698,9 @@ static UINT wined3d_cs_exec_query_issue(struct wined3d_cs *cs, const void *data) + + query->query_ops->query_issue(query, op->flags); + +- if (op->flags & WINED3DISSUE_END) +- InterlockedIncrement(&query->counter_worker); ++ if (wined3d_settings.cs_multithreaded && op->flags & WINED3DISSUE_END ++ && list_empty(&query->poll_list_entry)) ++ list_add_tail(&cs->query_poll_list, &query->poll_list_entry); + + return sizeof(*op); + } +@@ -1727,37 +1717,6 @@ void wined3d_cs_emit_query_issue(struct wined3d_cs *cs, struct wined3d_query *qu + cs->ops->submit(cs, sizeof(*op)); + } + +-static UINT wined3d_cs_exec_query_get_data(struct wined3d_cs *cs, const void *data) +-{ +- const struct wined3d_cs_query_get_data *op = data; +- struct wined3d_query *query = op->query; +- +- *op->ret = query->query_ops->query_get_data(query, op->data, op->data_size, op->flags); +- +- return sizeof(*op); +-} +- +-void wined3d_cs_emit_query_get_data(struct wined3d_cs *cs, struct wined3d_query *query, void *data, +- UINT data_size, DWORD flags, HRESULT *ret) +-{ +- struct wined3d_cs_query_get_data *op; +- +- op = cs->ops->require_space(cs, sizeof(*op)); +- op->opcode = WINED3D_CS_OP_QUERY_GET_DATA; +- op->query = query; +- op->data = data; +- op->data_size = data_size; +- op->flags = flags; +- op->ret = ret; +- +- cs->ops->submit(cs, sizeof(*op)); +- +- if (wined3d_settings.cs_multithreaded) +- FIXME("Query handling is not particularly fast yet\n"); +- +- cs->ops->finish(cs); +-} +- + static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = + { + /* WINED3D_CS_OP_NOP */ wined3d_cs_exec_nop, +@@ -1804,7 +1763,6 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* WINED3D_CS_OP_RESOURCE_MAP */ wined3d_cs_exec_resource_map, + /* WINED3D_CS_OP_RESOURCE_UNMAP */ wined3d_cs_exec_resource_unmap, + /* WINED3D_CS_OP_QUERY_ISSUE */ wined3d_cs_exec_query_issue, +- /* WINED3D_CS_OP_QUERY_GET_DATA */ wined3d_cs_exec_query_get_data, + }; + + static void *wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size) +@@ -1919,17 +1877,45 @@ void wined3d_cs_switch_onscreen_ds(struct wined3d_cs *cs, + wined3d_surface_incref(cs->onscreen_depth_stencil); + } + ++static inline void poll_queries(struct wined3d_cs *cs) ++{ ++ struct wined3d_query *query, *cursor; ++ ++ LIST_FOR_EACH_ENTRY_SAFE(query, cursor, &cs->query_poll_list, struct wined3d_query, poll_list_entry) ++ { ++ BOOL ret; ++ ++ ret = query->query_ops->query_poll(query); ++ if (ret) ++ { ++ list_remove(&query->poll_list_entry); ++ list_init(&query->poll_list_entry); ++ InterlockedIncrement(&query->counter_retrieved); ++ } ++ } ++} ++ + static DWORD WINAPI wined3d_cs_run(void *thread_param) + { + struct wined3d_cs *cs = thread_param; + enum wined3d_cs_op opcode; + LONG tail; ++ char poll = 0; + + TRACE("Started.\n"); + ++ list_init(&cs->query_poll_list); + cs->thread_id = GetCurrentThreadId(); + for (;;) + { ++ if (poll == 10) ++ { ++ poll = 0; ++ poll_queries(cs); ++ } ++ else ++ poll++; ++ + if (*((volatile LONG *)&cs->queue.head) == cs->queue.tail) + { + continue; +diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c +index bea03ed..621a9d7 100644 +--- a/dlls/wined3d/query.c ++++ b/dlls/wined3d/query.c +@@ -241,6 +241,15 @@ ULONG CDECL wined3d_query_decref(struct wined3d_query *query) + + if (!refcount) + { ++ if (wined3d_settings.cs_multithreaded) ++ { ++ struct wined3d_device *device = query->device; ++ ++ FIXME("waiting for cs\n"); ++ wined3d_cs_emit_glfinish(device->cs); ++ device->cs->ops->finish(device->cs); ++ } ++ + /* 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 +@@ -275,20 +284,10 @@ ULONG CDECL wined3d_query_decref(struct wined3d_query *query) + HRESULT CDECL wined3d_query_get_data(struct wined3d_query *query, + void *data, UINT data_size, DWORD flags) + { +- HRESULT hr; + TRACE("query %p, data %p, data_size %u, flags %#x.\n", + query, data, data_size, flags); + +- if (query->counter_main != query->counter_worker) +- { +- TRACE("D3DISSUE_END command not submitted to GL yet\n"); +- return S_FALSE; +- } +- +- wined3d_cs_emit_query_get_data(query->device->cs, query, data, data_size, +- flags, &hr); +- +- return hr; ++ return query->query_ops->query_get_data(query, data, data_size, flags); + } + + UINT CDECL wined3d_query_get_data_size(const struct wined3d_query *query) +@@ -317,15 +316,10 @@ static void fill_query_data(void *out, unsigned int out_size, const void *result + static HRESULT wined3d_occlusion_query_ops_get_data(struct wined3d_query *query, + void *data, DWORD size, DWORD flags) + { +- 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; ++ struct wined3d_occlusion_query *oq = query->extendedData; + 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; +@@ -339,6 +333,8 @@ static HRESULT wined3d_occlusion_query_ops_get_data(struct wined3d_query *query, + return S_OK; + } + ++ TRACE("(%p) : type D3DQUERY_OCCLUSION, data %p, size %#x, flags %#x.\n", query, data, size, flags); ++ + if (query->state == QUERY_BUILDING) + { + /* Msdn says this returns an error, but our tests show that S_FALSE is returned */ +@@ -354,12 +350,37 @@ static HRESULT wined3d_occlusion_query_ops_get_data(struct wined3d_query *query, + return S_OK; + } + ++ if (!wined3d_settings.cs_multithreaded) ++ { ++ if (!query->query_ops->query_poll(query)) ++ return S_FALSE; ++ } ++ else if (query->counter_main != query->counter_retrieved) ++ { ++ return S_FALSE; ++ } ++ ++ if (data) ++ fill_query_data(data, size, &oq->samples, sizeof(oq->samples)); ++ ++ return S_OK; ++} ++ ++static BOOL wined3d_occlusion_query_ops_poll(struct wined3d_query *query) ++{ ++ 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; ++ BOOL ret; ++ + 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; ++ oq->samples = 1; ++ return TRUE; + } + + context = context_acquire(query->device, oq->context->current_rt); +@@ -370,68 +391,78 @@ static HRESULT wined3d_occlusion_query_ops_get_data(struct wined3d_query *query, + + if (available) + { +- if (size) +- { +- GL_EXTCALL(glGetQueryObjectuivARB(oq->id, GL_QUERY_RESULT_ARB, &samples)); +- checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT)"); +- TRACE("Returning %d samples.\n", samples); +- fill_query_data(data, size, &samples, sizeof(samples)); +- } +- res = S_OK; ++ GL_EXTCALL(glGetQueryObjectuivARB(oq->id, GL_QUERY_RESULT_ARB, &samples)); ++ checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT)"); ++ TRACE("Returning %d samples.\n", samples); ++ oq->samples = samples; ++ ret = TRUE; + } + else + { +- res = S_FALSE; ++ ret = FALSE; + } + + context_release(context); + +- return res; ++ return ret; + } + +-static HRESULT wined3d_event_query_ops_get_data(struct wined3d_query *query, +- void *data, DWORD size, DWORD flags) ++static BOOL wined3d_event_query_ops_poll(struct wined3d_query *query) + { + 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; ++ return TRUE; + + case WINED3D_EVENT_QUERY_WAITING: +- signaled = FALSE; +- fill_query_data(data, size, &signaled, sizeof(signaled)); +- break; ++ return FALSE; + + 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; ++ return TRUE; + + case WINED3D_EVENT_QUERY_ERROR: + ERR("The GL event query failed, returning D3DERR_INVALIDCALL\n"); +- return WINED3DERR_INVALIDCALL; ++ return TRUE; ++ ++ default: ++ ERR("Unexpected wined3d_event_query_test result %u\n", ret); ++ return TRUE; ++ } ++} ++ ++static HRESULT wined3d_event_query_ops_get_data(struct wined3d_query *query, ++ void *pData, DWORD dwSize, DWORD flags) ++{ ++ struct wined3d_event_query *event_query = query->extendedData; ++ BOOL *data = pData; ++ enum wined3d_event_query_result ret; ++ ++ TRACE("query %p, pData %p, dwSize %#x, flags %#x.\n", query, pData, dwSize, flags); ++ ++ if (!pData || !dwSize) return S_OK; ++ if (!event_query) ++ { ++ WARN("Event query not supported by GL, reporting GPU idle.\n"); ++ *data = TRUE; ++ return S_OK; + } + ++ if (!wined3d_settings.cs_multithreaded) ++ ret = query->query_ops->query_poll(query); ++ else if (query->counter_main != query->counter_retrieved) ++ ret = FALSE; ++ else ++ ret = TRUE; ++ ++ if (data) ++ fill_query_data(data, dwSize, &ret, sizeof(ret)); ++ + return S_OK; + } + +@@ -561,33 +592,57 @@ 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; ++ ++ TRACE("(%p) : type D3DQUERY_TIMESTAMP, data %p, size %#x, flags %#x.\n", query, data, size, flags); ++ ++ if (query->state == QUERY_CREATED) ++ { ++ UINT64 zero = 0; ++ /* 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"); ++ if (data) ++ fill_query_data(data, size, &zero, sizeof(zero)); ++ return S_OK; ++ } ++ ++ if (!wined3d_settings.cs_multithreaded) ++ { ++ if (!query->query_ops->query_poll(query)) ++ return S_FALSE; ++ } ++ else if (query->counter_main != query->counter_retrieved) ++ { ++ return S_FALSE; ++ } ++ ++ if (data) ++ fill_query_data(data, size, &tq->timestamp, sizeof(tq->timestamp)); ++ ++ return S_OK; ++} ++ ++static BOOL wined3d_timestamp_query_ops_poll(struct wined3d_query *query) ++{ ++ 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; ++ BOOL ret; + +- 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) ++ if (!gl_info->supported[ARB_TIMER_QUERY]) + { +- /* 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; ++ TRACE("Faking timestamp.\n"); ++ QueryPerformanceCounter((LARGE_INTEGER *)&tq->timestamp); ++ return TRUE; + } + + 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; ++ tq->timestamp = 1; ++ return TRUE; + } + + context = context_acquire(query->device, tq->context->current_rt); +@@ -598,23 +653,20 @@ static HRESULT wined3d_timestamp_query_ops_get_data(struct wined3d_query *query, + + if (available) + { +- if (size) +- { +- GL_EXTCALL(glGetQueryObjectui64v(tq->id, GL_QUERY_RESULT_ARB, ×tamp)); +- checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT)"); +- TRACE("Returning timestamp %s.\n", wine_dbgstr_longlong(timestamp)); +- fill_query_data(data, size, ×tamp, sizeof(timestamp)); +- } +- res = S_OK; ++ GL_EXTCALL(glGetQueryObjectui64v(tq->id, GL_QUERY_RESULT_ARB, ×tamp)); ++ checkGLcall("glGetQueryObjectuivARB(GL_QUERY_RESULT)"); ++ TRACE("Returning timestamp %s.\n", wine_dbgstr_longlong(timestamp)); ++ tq->timestamp = timestamp; ++ ret = TRUE; + } + else + { +- res = S_FALSE; ++ ret = FALSE; + } + + context_release(context); + +- return res; ++ return ret; + } + + static void wined3d_timestamp_query_ops_issue(struct wined3d_query *query, DWORD flags) +@@ -657,15 +709,14 @@ static HRESULT wined3d_timestamp_disjoint_query_ops_get_data(struct wined3d_quer + 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 = {FALSE, 1000 * 1000 * 1000}; + + if (query->state == QUERY_BUILDING) + { +- TRACE("Query is building, returning S_FALSE.\n"); +- return S_FALSE; ++ TRACE("Query is building, returning S_FALSE.\n"); ++ return S_FALSE; + } + + fill_query_data(data, size, &disjoint_data, sizeof(disjoint_data)); +@@ -679,6 +730,11 @@ static HRESULT wined3d_timestamp_disjoint_query_ops_get_data(struct wined3d_quer + return S_OK; + } + ++static BOOL wined3d_timestamp_disjoint_query_ops_poll(struct wined3d_query *query) ++{ ++ return TRUE; ++} ++ + static void wined3d_timestamp_disjoint_query_ops_issue(struct wined3d_query *query, DWORD flags) + { + TRACE("query %p, flags %#x.\n", query, flags); +@@ -692,24 +748,28 @@ static void wined3d_timestamp_disjoint_query_ops_issue(struct wined3d_query *que + static const struct wined3d_query_ops event_query_ops = + { + wined3d_event_query_ops_get_data, ++ wined3d_event_query_ops_poll, + wined3d_event_query_ops_issue, + }; + + static const struct wined3d_query_ops occlusion_query_ops = + { + wined3d_occlusion_query_ops_get_data, ++ wined3d_occlusion_query_ops_poll, + wined3d_occlusion_query_ops_issue, + }; + + static const struct wined3d_query_ops timestamp_query_ops = + { + wined3d_timestamp_query_ops_get_data, ++ wined3d_timestamp_query_ops_poll, + wined3d_timestamp_query_ops_issue, + }; + + static const struct wined3d_query_ops timestamp_disjoint_query_ops = + { + wined3d_timestamp_disjoint_query_ops_get_data, ++ wined3d_timestamp_disjoint_query_ops_poll, + wined3d_timestamp_disjoint_query_ops_issue, + }; + +@@ -810,6 +870,7 @@ static HRESULT query_init(struct wined3d_query *query, struct wined3d_device *de + query->state = QUERY_CREATED; + query->device = device; + query->ref = 1; ++ list_init(&query->poll_list_entry); + + return WINED3D_OK; + } +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 3fd7fa7..7bda9f0 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -1051,6 +1051,7 @@ struct wined3d_occlusion_query + struct list entry; + GLuint id; + struct wined3d_context *context; ++ DWORD samples; + }; + + union wined3d_gl_query_object +@@ -1086,6 +1087,7 @@ struct wined3d_timestamp_query + struct list entry; + GLuint id; + struct wined3d_context *context; ++ UINT64 timestamp; + }; + + void context_alloc_timestamp_query(struct wined3d_context *context, struct wined3d_timestamp_query *query) DECLSPEC_HIDDEN; +@@ -2564,6 +2566,7 @@ struct wined3d_cs + struct wined3d_cs_queue queue; + + LONG pending_presents; ++ struct list query_poll_list; + }; + + struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device) DECLSPEC_HIDDEN; +@@ -2657,6 +2660,7 @@ enum query_state { + struct wined3d_query_ops + { + HRESULT (*query_get_data)(struct wined3d_query *query, void *data, DWORD data_size, DWORD flags); ++ BOOL (*query_poll)(struct wined3d_query *query); + void (*query_issue)(struct wined3d_query *query, DWORD flags); + }; + +@@ -2672,7 +2676,8 @@ struct wined3d_query + DWORD data_size; + void *extendedData; + +- LONG counter_main, counter_worker; ++ LONG counter_main, counter_retrieved; ++ struct list poll_list_entry; + }; + + /* TODO: Add tests and support for FLOAT16_4 POSITIONT, D3DCOLOR position, other +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0088-wined3d-Introduce-a-separate-queue-for-priority-comm.patch b/patches/wined3d-CSMT_Main/0088-wined3d-Introduce-a-separate-queue-for-priority-comm.patch new file mode 100644 index 00000000..824cb03e --- /dev/null +++ b/patches/wined3d-CSMT_Main/0088-wined3d-Introduce-a-separate-queue-for-priority-comm.patch @@ -0,0 +1,268 @@ +From 0a14b53f4dcb38e852db14d186d14c8526f3549a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Sat, 6 Jul 2013 19:18:03 +0200 +Subject: wined3d: Introduce a separate queue for priority commands + +--- + dlls/wined3d/cs.c | 128 ++++++++++++++++++++++++++++++++++------- + dlls/wined3d/wined3d_private.h | 5 +- + 2 files changed, 110 insertions(+), 23 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 68e1ed7..a7f7694 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -372,7 +372,7 @@ struct wined3d_cs_query_issue + DWORD flags; + }; + +-static void wined3d_cs_submit(struct wined3d_cs *cs, size_t size) ++static void wined3d_cs_mt_submit(struct wined3d_cs *cs, size_t size) + { + LONG new_val = (cs->queue.head + size) & (WINED3D_CS_QUEUE_SIZE - 1); + /* There is only one thread writing to queue.head, InterlockedExchange +@@ -380,6 +380,14 @@ static void wined3d_cs_submit(struct wined3d_cs *cs, size_t size) + InterlockedExchange(&cs->queue.head, new_val); + } + ++static void wined3d_cs_mt_submit_prio(struct wined3d_cs *cs, size_t size) ++{ ++ LONG new_val = (cs->prio_queue.head + size) & (WINED3D_CS_QUEUE_SIZE - 1); ++ /* There is only one thread writing to queue.head, InterlockedExchange ++ * is used for the memory barrier. */ ++ InterlockedExchange(&cs->prio_queue.head, new_val); ++} ++ + static UINT wined3d_cs_exec_nop(struct wined3d_cs *cs, const void *data) + { + return sizeof(enum wined3d_cs_op); +@@ -413,15 +421,16 @@ static void wined3d_cs_emit_fence(struct wined3d_cs *cs, BOOL *signalled) + cs->ops->submit(cs, sizeof(*op)); + } + +-static void wined3d_cs_finish(struct wined3d_cs *cs) ++static void wined3d_cs_emit_fence_prio(struct wined3d_cs *cs, BOOL *signalled) + { +- BOOL fence; ++ struct wined3d_cs_fence *op; + +- wined3d_cs_emit_fence(cs, &fence); ++ *signalled = FALSE; + +- /* A busy wait should be fine, we're not supposed to have to wait very +- * long. */ +- while (!InterlockedCompareExchange(&fence, TRUE, TRUE)); ++ op = cs->ops->require_space_prio(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_FENCE; ++ op->signalled = signalled; ++ cs->ops->submit_prio(cs, sizeof(*op)); + } + + static UINT wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data) +@@ -1765,9 +1774,9 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* WINED3D_CS_OP_QUERY_ISSUE */ wined3d_cs_exec_query_issue, + }; + +-static void *wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size) ++static inline void *_wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size, BOOL prio) + { +- struct wined3d_cs_queue *queue = &cs->queue; ++ 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) +@@ -1775,7 +1784,7 @@ static void *wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size) + struct wined3d_cs_skip *skip; + size_t nop_size = queue_size - queue->head; + +- skip = wined3d_cs_mt_require_space(cs, nop_size); ++ skip = _wined3d_cs_mt_require_space(cs, nop_size, prio); + if (nop_size < sizeof(*skip)) + { + skip->opcode = WINED3D_CS_OP_NOP; +@@ -1786,7 +1795,11 @@ static void *wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size) + skip->size = nop_size; + } + +- cs->ops->submit(cs, nop_size); ++ if (prio) ++ cs->ops->submit_prio(cs, nop_size); ++ else ++ cs->ops->submit(cs, nop_size); ++ + assert(!queue->head); + } + +@@ -1813,12 +1826,15 @@ static void *wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size) + return &queue->data[queue->head]; + } + +-static const struct wined3d_cs_ops wined3d_cs_mt_ops = ++static inline void *wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size) + { +- wined3d_cs_mt_require_space, +- wined3d_cs_submit, +- wined3d_cs_finish, +-}; ++ 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. */ +@@ -1829,9 +1845,63 @@ static void wined3d_cs_emit_stop(struct wined3d_cs *cs) + op = wined3d_cs_mt_require_space(cs, sizeof(*op)); + op->opcode = WINED3D_CS_OP_STOP; + +- wined3d_cs_submit(cs, sizeof(*op)); ++ 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, ++ wined3d_cs_mt_finish, ++ wined3d_cs_mt_finish_prio, ++}; ++ + static void wined3d_cs_st_submit(struct wined3d_cs *cs, size_t size) + { + enum wined3d_cs_op opcode = *(const enum wined3d_cs_op *)&cs->queue.data; +@@ -1857,8 +1927,11 @@ static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size) + static const struct wined3d_cs_ops wined3d_cs_st_ops = + { + wined3d_cs_st_require_space, ++ wined3d_cs_st_require_space, ++ wined3d_cs_st_submit, + wined3d_cs_st_submit, + wined3d_cs_st_finish, ++ wined3d_cs_st_finish, + }; + + void wined3d_cs_switch_onscreen_ds(struct wined3d_cs *cs, +@@ -1901,6 +1974,7 @@ static DWORD WINAPI wined3d_cs_run(void *thread_param) + enum wined3d_cs_op opcode; + LONG tail; + char poll = 0; ++ struct wined3d_cs_queue *queue; + + TRACE("Started.\n"); + +@@ -1916,13 +1990,23 @@ static DWORD WINAPI wined3d_cs_run(void *thread_param) + else + poll++; + +- if (*((volatile LONG *)&cs->queue.head) == cs->queue.tail) ++ if (*((volatile LONG *)&cs->prio_queue.head) != cs->prio_queue.tail) ++ { ++ queue = &cs->prio_queue; ++ } ++ else if (*((volatile LONG *)&cs->queue.head) != cs->queue.tail) ++ { ++ queue = &cs->queue; ++ if (*((volatile LONG *)&cs->prio_queue.head) != cs->prio_queue.tail) ++ queue = &cs->prio_queue; ++ } ++ else + { + continue; + } + +- tail = cs->queue.tail; +- opcode = *(const enum wined3d_cs_op *)&cs->queue.data[tail]; ++ tail = queue->tail; ++ opcode = *(const enum wined3d_cs_op *)&queue->data[tail]; + + if (opcode >= WINED3D_CS_OP_STOP) + { +@@ -1931,9 +2015,9 @@ static DWORD WINAPI wined3d_cs_run(void *thread_param) + goto done; + } + +- tail += wined3d_cs_op_handlers[opcode](cs, &cs->queue.data[tail]); ++ tail += wined3d_cs_op_handlers[opcode](cs, &queue->data[tail]); + tail &= (WINED3D_CS_QUEUE_SIZE - 1); +- InterlockedExchange(&cs->queue.tail, tail); ++ InterlockedExchange(&queue->tail, tail); + } + + done: +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 7bda9f0..cf01a6a 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2550,8 +2550,11 @@ struct wined3d_cs_queue + struct wined3d_cs_ops + { + void *(*require_space)(struct wined3d_cs *cs, size_t size); ++ void *(*require_space_prio)(struct wined3d_cs *cs, size_t size); + void (*submit)(struct wined3d_cs *cs, size_t size); ++ void (*submit_prio)(struct wined3d_cs *cs, size_t size); + void (*finish)(struct wined3d_cs *cs); ++ void (*finish_prio)(struct wined3d_cs *cs); + }; + + struct wined3d_cs +@@ -2563,7 +2566,7 @@ struct wined3d_cs + DWORD thread_id; + struct wined3d_surface *onscreen_depth_stencil; + +- struct wined3d_cs_queue queue; ++ struct wined3d_cs_queue queue, prio_queue; + + LONG pending_presents; + struct list query_poll_list; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0089-wined3d-Destroy-queries-through-the-CS.patch b/patches/wined3d-CSMT_Main/0089-wined3d-Destroy-queries-through-the-CS.patch new file mode 100644 index 00000000..bc490c7f --- /dev/null +++ b/patches/wined3d-CSMT_Main/0089-wined3d-Destroy-queries-through-the-CS.patch @@ -0,0 +1,183 @@ +From ef12b024a49a4390df02fad20938e04d5cfae35e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Sat, 6 Jul 2013 21:54:45 +0200 +Subject: wined3d: Destroy queries through the CS + +--- + dlls/wined3d/cs.c | 31 ++++++++++++++++++++ + dlls/wined3d/query.c | 66 +++++++++++++++++++----------------------- + dlls/wined3d/wined3d_private.h | 3 ++ + 3 files changed, 64 insertions(+), 36 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index a7f7694..b2af05b 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -68,6 +68,7 @@ enum wined3d_cs_op + WINED3D_CS_OP_RESOURCE_MAP, + WINED3D_CS_OP_RESOURCE_UNMAP, + WINED3D_CS_OP_QUERY_ISSUE, ++ WINED3D_CS_OP_QUERY_DESTROY, + WINED3D_CS_OP_STOP, + }; + +@@ -372,6 +373,12 @@ struct wined3d_cs_query_issue + DWORD flags; + }; + ++struct wined3d_cs_query_destroy ++{ ++ enum wined3d_cs_op opcode; ++ struct wined3d_query *query; ++}; ++ + static void wined3d_cs_mt_submit(struct wined3d_cs *cs, size_t size) + { + LONG new_val = (cs->queue.head + size) & (WINED3D_CS_QUEUE_SIZE - 1); +@@ -1726,6 +1733,29 @@ void wined3d_cs_emit_query_issue(struct wined3d_cs *cs, struct wined3d_query *qu + cs->ops->submit(cs, sizeof(*op)); + } + ++static UINT wined3d_cs_exec_query_destroy(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_query_destroy *op = data; ++ ++ if (!list_empty(&op->query->poll_list_entry)) ++ list_remove(&op->query->poll_list_entry); ++ ++ wined3d_query_destroy(op->query); ++ ++ return sizeof(*op); ++} ++ ++void wined3d_cs_emit_query_destroy(struct wined3d_cs *cs, struct wined3d_query *query) ++{ ++ struct wined3d_cs_query_destroy *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_QUERY_DESTROY; ++ op->query = query; ++ ++ cs->ops->submit(cs, sizeof(*op)); ++} ++ + static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = + { + /* WINED3D_CS_OP_NOP */ wined3d_cs_exec_nop, +@@ -1772,6 +1802,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* WINED3D_CS_OP_RESOURCE_MAP */ wined3d_cs_exec_resource_map, + /* WINED3D_CS_OP_RESOURCE_UNMAP */ wined3d_cs_exec_resource_unmap, + /* WINED3D_CS_OP_QUERY_ISSUE */ wined3d_cs_exec_query_issue, ++ /* WINED3D_CS_OP_QUERY_DESTROY */ wined3d_cs_exec_query_destroy, + }; + + static inline void *_wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size, BOOL prio) +diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c +index 621a9d7..f377eea 100644 +--- a/dlls/wined3d/query.c ++++ b/dlls/wined3d/query.c +@@ -233,50 +233,44 @@ ULONG CDECL wined3d_query_incref(struct wined3d_query *query) + return refcount; + } + +-ULONG CDECL wined3d_query_decref(struct wined3d_query *query) ++void wined3d_query_destroy(struct wined3d_query *query) + { +- ULONG refcount = InterlockedDecrement(&query->ref); +- +- TRACE("%p decreasing refcount to %u.\n", query, refcount); ++ /* 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 (!refcount) ++ if (oq->context) context_free_occlusion_query(oq); ++ HeapFree(GetProcessHeap(), 0, query->extendedData); ++ } ++ else if (query->type == WINED3D_QUERY_TYPE_TIMESTAMP) + { +- if (wined3d_settings.cs_multithreaded) +- { +- struct wined3d_device *device = query->device; ++ struct wined3d_timestamp_query *tq = query->extendedData; + +- FIXME("waiting for cs\n"); +- wined3d_cs_emit_glfinish(device->cs); +- device->cs->ops->finish(device->cs); +- } ++ if (tq->context) ++ context_free_timestamp_query(tq); ++ HeapFree(GetProcessHeap(), 0, query->extendedData); ++ } + +- /* 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; ++ HeapFree(GetProcessHeap(), 0, query); ++} + +- 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; ++ULONG CDECL wined3d_query_decref(struct wined3d_query *query) ++{ ++ ULONG refcount = InterlockedDecrement(&query->ref); + +- if (tq->context) +- context_free_timestamp_query(tq); +- HeapFree(GetProcessHeap(), 0, query->extendedData); +- } ++ TRACE("%p decreasing refcount to %u.\n", query, refcount); + +- HeapFree(GetProcessHeap(), 0, query); +- } ++ if (!refcount) ++ wined3d_cs_emit_query_destroy(query->device->cs, query); + + return refcount; + } +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index cf01a6a..28badf6 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2649,6 +2649,7 @@ void wined3d_cs_emit_query_issue(struct wined3d_cs *cs, struct wined3d_query *qu + DWORD flags) DECLSPEC_HIDDEN; + void wined3d_cs_emit_query_get_data(struct wined3d_cs *cs, struct wined3d_query *query, void *data, + UINT data_size, DWORD flags, HRESULT *ret) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_query_destroy(struct wined3d_cs *cs, struct wined3d_query *query) DECLSPEC_HIDDEN; + + /* 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 +@@ -2683,6 +2684,8 @@ struct wined3d_query + struct list poll_list_entry; + }; + ++void wined3d_query_destroy(struct wined3d_query *query) DECLSPEC_HIDDEN; ++ + /* TODO: Add tests and support for FLOAT16_4 POSITIONT, D3DCOLOR position, other + * fixed function semantics as D3DCOLOR or FLOAT16 */ + enum wined3d_buffer_conversion_type +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0090-wined3d-Separate-main-and-worker-thread-query-state.patch b/patches/wined3d-CSMT_Main/0090-wined3d-Separate-main-and-worker-thread-query-state.patch new file mode 100644 index 00000000..17025838 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0090-wined3d-Separate-main-and-worker-thread-query-state.patch @@ -0,0 +1,138 @@ +From 1a53e5cd7279145ad9f78f2970a186f488216d6b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Wed, 24 Jul 2013 16:34:17 +0200 +Subject: wined3d: Separate main and worker thread query state + +--- + dlls/wined3d/query.c | 34 ++++++++++++---------------------- + dlls/wined3d/wined3d_private.h | 1 + + 2 files changed, 13 insertions(+), 22 deletions(-) + +diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c +index f377eea..97483a2 100644 +--- a/dlls/wined3d/query.c ++++ b/dlls/wined3d/query.c +@@ -299,6 +299,12 @@ HRESULT CDECL wined3d_query_issue(struct wined3d_query *query, DWORD flags) + query->counter_main++; + + wined3d_cs_emit_query_issue(query->device->cs, query, flags); ++ ++ if (flags & WINED3DISSUE_BEGIN) ++ query->state = QUERY_BUILDING; ++ else ++ query->state = QUERY_SIGNALLED; ++ + return WINED3D_OK; + } + +@@ -493,11 +499,6 @@ static void wined3d_event_query_ops_issue(struct wined3d_query *query, DWORD fla + /* 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; + } + + static void wined3d_occlusion_query_ops_issue(struct wined3d_query *query, DWORD flags) +@@ -515,7 +516,7 @@ static void wined3d_occlusion_query_ops_issue(struct wined3d_query *query, DWORD + /* This is allowed according to msdn and our tests. Reset the query and restart */ + if (flags & WINED3DISSUE_BEGIN) + { +- if (query->state == QUERY_BUILDING) ++ if (oq->started) + { + if (oq->context->tid != GetCurrentThreadId()) + { +@@ -544,6 +545,7 @@ static void wined3d_occlusion_query_ops_issue(struct wined3d_query *query, DWORD + checkGLcall("glBeginQuery()"); + + context_release(context); ++ oq->started = TRUE; + } + if (flags & WINED3DISSUE_END) + { +@@ -551,7 +553,7 @@ static void wined3d_occlusion_query_ops_issue(struct wined3d_query *query, DWORD + * our tests show that it returns OK. But OpenGL doesn't like it, so avoid + * generating an error + */ +- if (query->state == QUERY_BUILDING) ++ if (oq->started) + { + if (oq->context->tid != GetCurrentThreadId()) + { +@@ -567,6 +569,7 @@ static void wined3d_occlusion_query_ops_issue(struct wined3d_query *query, DWORD + context_release(context); + } + } ++ oq->started = FALSE; + } + } + else +@@ -574,11 +577,6 @@ static void wined3d_occlusion_query_ops_issue(struct wined3d_query *query, DWORD + FIXME("%p Occlusion queries not supported.\n", query); + } + +- if (flags & WINED3DISSUE_BEGIN) +- query->state = QUERY_BUILDING; +- else +- query->state = QUERY_SIGNALLED; +- + return; + } + +@@ -694,9 +692,6 @@ static void wined3d_timestamp_query_ops_issue(struct wined3d_query *query, DWORD + { + ERR("Timestamp queries not supported.\n"); + } +- +- if (flags & WINED3DISSUE_END) +- query->state = QUERY_SIGNALLED; + } + + static HRESULT wined3d_timestamp_disjoint_query_ops_get_data(struct wined3d_query *query, +@@ -732,11 +727,6 @@ static BOOL wined3d_timestamp_disjoint_query_ops_poll(struct wined3d_query *quer + static void 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; + } + + static const struct wined3d_query_ops event_query_ops = +@@ -785,13 +775,13 @@ static HRESULT query_init(struct wined3d_query *query, struct wined3d_device *de + } + query->query_ops = &occlusion_query_ops; + query->data_size = sizeof(DWORD); +- query->extendedData = HeapAlloc(GetProcessHeap(), 0, sizeof(struct wined3d_occlusion_query)); ++ query->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ++ 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; + break; + + case WINED3D_QUERY_TYPE_EVENT: +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 28badf6..ec474dd 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -1052,6 +1052,7 @@ struct wined3d_occlusion_query + GLuint id; + struct wined3d_context *context; + DWORD samples; ++ BOOL started; + }; + + union wined3d_gl_query_object +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0091-wined3d-Don-t-poll-queries-that-failed-to-start.patch b/patches/wined3d-CSMT_Main/0091-wined3d-Don-t-poll-queries-that-failed-to-start.patch new file mode 100644 index 00000000..76f5f216 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0091-wined3d-Don-t-poll-queries-that-failed-to-start.patch @@ -0,0 +1,134 @@ +From 3ee3d46182ba5a4f968d2bed318a80e9380b1246 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Wed, 24 Jul 2013 17:27:35 +0200 +Subject: wined3d: Don't poll queries that failed to start + +--- + dlls/wined3d/cs.c | 5 +++-- + dlls/wined3d/query.c | 21 +++++++++++++++------ + dlls/wined3d/wined3d_private.h | 2 +- + 3 files changed, 19 insertions(+), 9 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index b2af05b..4c0695a 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -1711,10 +1711,11 @@ static UINT wined3d_cs_exec_query_issue(struct wined3d_cs *cs, const void *data) + { + const struct wined3d_cs_query_issue *op = data; + struct wined3d_query *query = op->query; ++ BOOL poll; + +- query->query_ops->query_issue(query, op->flags); ++ poll = query->query_ops->query_issue(query, op->flags); + +- if (wined3d_settings.cs_multithreaded && op->flags & WINED3DISSUE_END ++ if (wined3d_settings.cs_multithreaded && poll + && list_empty(&query->poll_list_entry)) + list_add_tail(&cs->query_poll_list, &query->poll_list_entry); + +diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c +index 97483a2..a42a1bd 100644 +--- a/dlls/wined3d/query.c ++++ b/dlls/wined3d/query.c +@@ -480,7 +480,7 @@ enum wined3d_query_type CDECL wined3d_query_get_type(const struct wined3d_query + return query->type; + } + +-static void wined3d_event_query_ops_issue(struct wined3d_query *query, DWORD flags) ++static BOOL wined3d_event_query_ops_issue(struct wined3d_query *query, DWORD flags) + { + TRACE("query %p, flags %#x.\n", query, flags); + +@@ -490,21 +490,24 @@ static void wined3d_event_query_ops_issue(struct wined3d_query *query, DWORD fla + struct wined3d_event_query *event_query = query->extendedData; + + /* Faked event query support */ +- if (!event_query) return; ++ if (!event_query) return FALSE; + + wined3d_event_query_issue(event_query, query->device); ++ return TRUE; + } + else if (flags & WINED3DISSUE_BEGIN) + { + /* Started implicitly at device creation */ + ERR("Event query issued with START flag - what to do?\n"); + } ++ return FALSE; + } + +-static void wined3d_occlusion_query_ops_issue(struct wined3d_query *query, DWORD flags) ++static BOOL 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; ++ BOOL poll = FALSE; + + TRACE("query %p, flags %#x.\n", query, flags); + +@@ -570,6 +573,7 @@ static void wined3d_occlusion_query_ops_issue(struct wined3d_query *query, DWORD + } + } + oq->started = FALSE; ++ poll = TRUE; + } + } + else +@@ -577,7 +581,7 @@ static void wined3d_occlusion_query_ops_issue(struct wined3d_query *query, DWORD + FIXME("%p Occlusion queries not supported.\n", query); + } + +- return; ++ return poll; + } + + static HRESULT wined3d_timestamp_query_ops_get_data(struct wined3d_query *query, +@@ -661,7 +665,7 @@ static BOOL wined3d_timestamp_query_ops_poll(struct wined3d_query *query) + return ret; + } + +-static void wined3d_timestamp_query_ops_issue(struct wined3d_query *query, DWORD flags) ++static BOOL wined3d_timestamp_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; +@@ -692,6 +696,10 @@ static void wined3d_timestamp_query_ops_issue(struct wined3d_query *query, DWORD + { + ERR("Timestamp queries not supported.\n"); + } ++ ++ if (flags & WINED3DISSUE_END) ++ return TRUE; ++ return FALSE; + } + + static HRESULT wined3d_timestamp_disjoint_query_ops_get_data(struct wined3d_query *query, +@@ -724,9 +732,10 @@ static BOOL wined3d_timestamp_disjoint_query_ops_poll(struct wined3d_query *quer + return TRUE; + } + +-static void wined3d_timestamp_disjoint_query_ops_issue(struct wined3d_query *query, DWORD flags) ++static BOOL wined3d_timestamp_disjoint_query_ops_issue(struct wined3d_query *query, DWORD flags) + { + TRACE("query %p, flags %#x.\n", query, flags); ++ return FALSE; + } + + static const struct wined3d_query_ops event_query_ops = +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index ec474dd..8dd9786 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2666,7 +2666,7 @@ struct wined3d_query_ops + { + HRESULT (*query_get_data)(struct wined3d_query *query, void *data, DWORD data_size, DWORD flags); + BOOL (*query_poll)(struct wined3d_query *query); +- void (*query_issue)(struct wined3d_query *query, DWORD flags); ++ BOOL (*query_issue)(struct wined3d_query *query, DWORD flags); + }; + + struct wined3d_query +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0092-wined3d-Remove-restated-queries-from-the-poll-list.patch b/patches/wined3d-CSMT_Main/0092-wined3d-Remove-restated-queries-from-the-poll-list.patch new file mode 100644 index 00000000..07bbeac4 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0092-wined3d-Remove-restated-queries-from-the-poll-list.patch @@ -0,0 +1,40 @@ +From d46500650ef16a6bd292705ce9896bc8b1427d99 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Wed, 24 Jul 2013 17:50:16 +0200 +Subject: wined3d: Remove restated queries from the poll list + +--- + dlls/wined3d/cs.c | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 4c0695a..5c19a17 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -1715,9 +1715,20 @@ static UINT wined3d_cs_exec_query_issue(struct wined3d_cs *cs, const void *data) + + poll = query->query_ops->query_issue(query, op->flags); + +- if (wined3d_settings.cs_multithreaded && poll +- && list_empty(&query->poll_list_entry)) +- list_add_tail(&cs->query_poll_list, &query->poll_list_entry); ++ if (wined3d_settings.cs_multithreaded) ++ { ++ if (poll && list_empty(&query->poll_list_entry)) ++ { ++ list_add_tail(&cs->query_poll_list, &query->poll_list_entry); ++ } ++ else if (!poll && !list_empty(&query->poll_list_entry)) ++ { ++ /* Can happen if occlusion queries are restarted. This discards the old ++ * result, polling it could result in a GL error */ ++ list_remove(&query->poll_list_entry); ++ list_init(&query->poll_list_entry); ++ } ++ } + + return sizeof(*op); + } +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0093-wined3d-Don-t-reset-the-query-state-if-it-doesn-t-ha.patch b/patches/wined3d-CSMT_Main/0093-wined3d-Don-t-reset-the-query-state-if-it-doesn-t-ha.patch new file mode 100644 index 00000000..cfe1cbda --- /dev/null +++ b/patches/wined3d-CSMT_Main/0093-wined3d-Don-t-reset-the-query-state-if-it-doesn-t-ha.patch @@ -0,0 +1,31 @@ +From 681469685b22ba7fedfbc808498028b518b890a0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Mon, 5 Aug 2013 13:07:42 +0200 +Subject: wined3d: Don't reset the query state if it doesn't have a ctx + +The CS recreates occlusion queries and changes the context variable. +This leads to incorrect query results. + +TODO: Before sending, find out why the line was there in the first place +and if it is needed with the multithreaded and/or singlethreaded CS. +--- + dlls/wined3d/query.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c +index a42a1bd..39d663a 100644 +--- a/dlls/wined3d/query.c ++++ b/dlls/wined3d/query.c +@@ -321,9 +321,6 @@ static HRESULT wined3d_occlusion_query_ops_get_data(struct wined3d_query *query, + struct wined3d_occlusion_query *oq = query->extendedData; + GLuint samples; + +- if (!oq->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 */ +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0094-wined3d-Put-this-into-the-query-poll-patch.patch b/patches/wined3d-CSMT_Main/0094-wined3d-Put-this-into-the-query-poll-patch.patch new file mode 100644 index 00000000..cffb61c1 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0094-wined3d-Put-this-into-the-query-poll-patch.patch @@ -0,0 +1,52 @@ +From 5797fdf345e0af334745c957771b6a7a770eecbc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Fri, 30 Aug 2013 13:53:48 +0200 +Subject: wined3d: Put this into the query poll patch + +--- + dlls/wined3d/cs.c | 12 ++++++++++++ + dlls/wined3d/query.c | 2 +- + 2 files changed, 13 insertions(+), 1 deletion(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 5c19a17..3540cb7 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -1728,6 +1728,18 @@ static UINT wined3d_cs_exec_query_issue(struct wined3d_cs *cs, const void *data) + list_remove(&query->poll_list_entry); + list_init(&query->poll_list_entry); + } ++ else if (op->flags & WINED3DISSUE_END) ++ { ++ /* Can happen when an occlusion query is ended without being started, ++ * in which case we don't want to poll, but still have to counter-balance ++ * the increment of the main counter (!poll && list_empty). ++ * ++ * This can also happen if an event query is re-issued before the first ++ * fence was reached (poll && !list_empty). In this case the query is ++ * already in the list and the poll function will check the new fence. ++ * We have to counter-balance the discarded increment. */ ++ InterlockedIncrement(&query->counter_retrieved); ++ } + } + + return sizeof(*op); +diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c +index 39d663a..f33b30e 100644 +--- a/dlls/wined3d/query.c ++++ b/dlls/wined3d/query.c +@@ -567,10 +567,10 @@ static BOOL wined3d_occlusion_query_ops_issue(struct wined3d_query *query, DWORD + checkGLcall("glEndQuery()"); + + context_release(context); ++ poll = TRUE; + } + } + oq->started = FALSE; +- poll = TRUE; + } + } + else +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0095-wined3d-Send-update_surface-commands-through-the-CS.patch b/patches/wined3d-CSMT_Main/0095-wined3d-Send-update_surface-commands-through-the-CS.patch new file mode 100644 index 00000000..62af97f7 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0095-wined3d-Send-update_surface-commands-through-the-CS.patch @@ -0,0 +1,128 @@ +From 961a8cb3c42a2969dd1500b4fc16adb4d47b514f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 1 Aug 2013 00:00:26 +0200 +Subject: wined3d: Send update_surface commands through the CS + +--- + dlls/wined3d/cs.c | 48 ++++++++++++++++++++++++++++++++++++++++++ + dlls/wined3d/device.c | 9 ++------ + dlls/wined3d/wined3d_private.h | 2 ++ + 3 files changed, 52 insertions(+), 7 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 3540cb7..3264d17 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -69,6 +69,7 @@ enum wined3d_cs_op + WINED3D_CS_OP_RESOURCE_UNMAP, + WINED3D_CS_OP_QUERY_ISSUE, + WINED3D_CS_OP_QUERY_DESTROY, ++ WINED3D_CS_OP_UPDATE_SURFACE, + WINED3D_CS_OP_STOP, + }; + +@@ -379,6 +380,15 @@ struct wined3d_cs_query_destroy + struct wined3d_query *query; + }; + ++struct wined3d_cs_update_surface ++{ ++ enum wined3d_cs_op opcode; ++ struct wined3d_surface *src, *dst; ++ RECT src_rect; ++ POINT dst_point; ++ BOOL has_src_rect, has_dst_point; ++}; ++ + static void wined3d_cs_mt_submit(struct wined3d_cs *cs, size_t size) + { + LONG new_val = (cs->queue.head + size) & (WINED3D_CS_QUEUE_SIZE - 1); +@@ -1780,6 +1790,43 @@ void wined3d_cs_emit_query_destroy(struct wined3d_cs *cs, struct wined3d_query * + cs->ops->submit(cs, sizeof(*op)); + } + ++static UINT wined3d_cs_exec_update_surface(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_update_surface *op = data; ++ ++ surface_upload_from_surface(op->dst, op->has_dst_point ? &op->dst_point : NULL, ++ op->src, op->has_src_rect ? &op->src_rect : NULL); ++ ++ return sizeof(*op); ++} ++ ++void wined3d_cs_emit_update_surface(struct wined3d_cs *cs, struct wined3d_surface *src, const RECT *src_rect, ++ struct wined3d_surface *dst, const POINT *dst_point) ++{ ++ struct wined3d_cs_update_surface *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_UPDATE_SURFACE; ++ op->src = src; ++ op->dst = dst; ++ op->has_src_rect = FALSE; ++ op->has_dst_point = FALSE; ++ ++ if (src_rect) ++ { ++ op->has_src_rect = TRUE; ++ op->src_rect = *src_rect; ++ } ++ ++ if (dst_point) ++ { ++ op->has_dst_point = TRUE; ++ op->dst_point = *dst_point; ++ } ++ ++ cs->ops->submit(cs, sizeof(*op)); ++} ++ + static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = + { + /* WINED3D_CS_OP_NOP */ wined3d_cs_exec_nop, +@@ -1827,6 +1874,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* WINED3D_CS_OP_RESOURCE_UNMAP */ wined3d_cs_exec_resource_unmap, + /* 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, + }; + + static inline void *_wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size, BOOL prio) +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index cd90c76..ed055f8 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -3796,14 +3796,9 @@ HRESULT CDECL wined3d_device_update_surface(struct wined3d_device *device, + return WINED3DERR_INVALIDCALL; + } + +- if (wined3d_settings.cs_multithreaded) +- { +- FIXME("Waiting for cs.\n"); +- wined3d_cs_emit_glfinish(device->cs); +- device->cs->ops->finish(device->cs); +- } ++ wined3d_cs_emit_update_surface(device->cs, src_surface, src_rect, dst_surface, dst_point); + +- return surface_upload_from_surface(dst_surface, dst_point, src_surface, src_rect); ++ return WINED3D_OK; + } + + void CDECL wined3d_device_copy_resource(struct wined3d_device *device, +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 8dd9786..07d1613 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2651,6 +2651,8 @@ void wined3d_cs_emit_query_issue(struct wined3d_cs *cs, struct wined3d_query *qu + void wined3d_cs_emit_query_get_data(struct wined3d_cs *cs, struct wined3d_query *query, void *data, + UINT data_size, DWORD flags, HRESULT *ret) DECLSPEC_HIDDEN; + void wined3d_cs_emit_query_destroy(struct wined3d_cs *cs, struct wined3d_query *query) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_update_surface(struct wined3d_cs *cs, struct wined3d_surface *src, ++ const RECT *src_rect, struct wined3d_surface *dst, const POINT *dst_point) DECLSPEC_HIDDEN; + + /* 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 +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0096-wined3d-Send-texture-preloads-through-the-CS.patch b/patches/wined3d-CSMT_Main/0096-wined3d-Send-texture-preloads-through-the-CS.patch new file mode 100644 index 00000000..fb0f1224 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0096-wined3d-Send-texture-preloads-through-the-CS.patch @@ -0,0 +1,107 @@ +From dd0852f22f9a3e04e9fefae6c0a3ac4913cc390d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 1 Aug 2013 00:10:40 +0200 +Subject: wined3d: Send texture preloads through the CS + +--- + dlls/wined3d/cs.c | 32 ++++++++++++++++++++++++++++++++ + dlls/wined3d/texture.c | 6 ++---- + dlls/wined3d/wined3d_private.h | 1 + + 3 files changed, 35 insertions(+), 4 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 3264d17..78e5010 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -70,6 +70,7 @@ enum wined3d_cs_op + WINED3D_CS_OP_QUERY_ISSUE, + WINED3D_CS_OP_QUERY_DESTROY, + WINED3D_CS_OP_UPDATE_SURFACE, ++ WINED3D_CS_OP_TEXTURE_PRELOAD, + WINED3D_CS_OP_STOP, + }; + +@@ -389,6 +390,12 @@ struct wined3d_cs_update_surface + BOOL has_src_rect, has_dst_point; + }; + ++struct wined3d_cs_texture_preload ++{ ++ enum wined3d_cs_op opcode; ++ struct wined3d_texture *texture; ++}; ++ + static void wined3d_cs_mt_submit(struct wined3d_cs *cs, size_t size) + { + LONG new_val = (cs->queue.head + size) & (WINED3D_CS_QUEUE_SIZE - 1); +@@ -1827,6 +1834,30 @@ void wined3d_cs_emit_update_surface(struct wined3d_cs *cs, struct wined3d_surfac + cs->ops->submit(cs, sizeof(*op)); + } + ++static UINT wined3d_cs_exec_texture_preload(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_texture_preload *op = data; ++ struct wined3d_context *context; ++ struct wined3d_texture *texture = op->texture; ++ ++ context = context_acquire(cs->device, NULL); ++ wined3d_texture_load(texture, context, texture->flags & WINED3D_TEXTURE_IS_SRGB); ++ context_release(context); ++ ++ return sizeof(*op); ++} ++ ++void wined3d_cs_emit_texture_preload(struct wined3d_cs *cs, struct wined3d_texture *texture) ++{ ++ struct wined3d_cs_texture_preload *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_TEXTURE_PRELOAD; ++ op->texture = texture; ++ ++ cs->ops->submit(cs, sizeof(*op)); ++} ++ + static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = + { + /* WINED3D_CS_OP_NOP */ wined3d_cs_exec_nop, +@@ -1875,6 +1906,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* 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, + }; + + static inline void *_wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size, BOOL prio) +diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c +index b7891d9..ea8589a 100644 +--- a/dlls/wined3d/texture.c ++++ b/dlls/wined3d/texture.c +@@ -569,10 +569,8 @@ void wined3d_texture_load(struct wined3d_texture *texture, + + void CDECL wined3d_texture_preload(struct wined3d_texture *texture) + { +- 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); ++ const struct wined3d_device *device = texture->resource.device; ++ wined3d_cs_emit_texture_preload(device->cs, texture); + } + + void * CDECL wined3d_texture_get_parent(const struct wined3d_texture *texture) +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 07d1613..de82b46 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2653,6 +2653,7 @@ void wined3d_cs_emit_query_get_data(struct wined3d_cs *cs, struct wined3d_query + void wined3d_cs_emit_query_destroy(struct wined3d_cs *cs, struct wined3d_query *query) DECLSPEC_HIDDEN; + void wined3d_cs_emit_update_surface(struct wined3d_cs *cs, struct wined3d_surface *src, + const RECT *src_rect, struct wined3d_surface *dst, const POINT *dst_point) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_texture_preload(struct wined3d_cs *cs, struct wined3d_texture *texture) DECLSPEC_HIDDEN; + + /* 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 +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0097-wined3d-Send-surface-preloads-through-the-CS.patch b/patches/wined3d-CSMT_Main/0097-wined3d-Send-surface-preloads-through-the-CS.patch new file mode 100644 index 00000000..fe17b171 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0097-wined3d-Send-surface-preloads-through-the-CS.patch @@ -0,0 +1,112 @@ +From 2f0bb40d8d1791180b93f3d4eccbf7c3f190d19e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 1 Aug 2013 00:15:58 +0200 +Subject: wined3d: Send surface preloads through the CS + +--- + dlls/wined3d/cs.c | 31 +++++++++++++++++++++++++++++++ + dlls/wined3d/surface.c | 5 +++-- + dlls/wined3d/wined3d_private.h | 1 + + 3 files changed, 35 insertions(+), 2 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 78e5010..4834dd4 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -71,6 +71,7 @@ enum wined3d_cs_op + WINED3D_CS_OP_QUERY_DESTROY, + WINED3D_CS_OP_UPDATE_SURFACE, + WINED3D_CS_OP_TEXTURE_PRELOAD, ++ WINED3D_CS_OP_SURFACE_PRELOAD, + WINED3D_CS_OP_STOP, + }; + +@@ -396,6 +397,12 @@ struct wined3d_cs_texture_preload + struct wined3d_texture *texture; + }; + ++struct wined3d_cs_surface_preload ++{ ++ enum wined3d_cs_op opcode; ++ struct wined3d_surface *surface; ++}; ++ + static void wined3d_cs_mt_submit(struct wined3d_cs *cs, size_t size) + { + LONG new_val = (cs->queue.head + size) & (WINED3D_CS_QUEUE_SIZE - 1); +@@ -1858,6 +1865,29 @@ void wined3d_cs_emit_texture_preload(struct wined3d_cs *cs, struct wined3d_textu + cs->ops->submit(cs, sizeof(*op)); + } + ++static UINT wined3d_cs_exec_surface_preload(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_surface_preload *op = data; ++ struct wined3d_context *context; ++ ++ context = context_acquire(cs->device, NULL); ++ wined3d_texture_preload(op->surface->container); ++ context_release(context); ++ ++ return sizeof(*op); ++} ++ ++void wined3d_cs_emit_surface_preload(struct wined3d_cs *cs, struct wined3d_surface *surface) ++{ ++ struct wined3d_cs_surface_preload *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_SURFACE_PRELOAD; ++ op->surface = surface; ++ ++ cs->ops->submit(cs, sizeof(*op)); ++} ++ + static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = + { + /* WINED3D_CS_OP_NOP */ wined3d_cs_exec_nop, +@@ -1907,6 +1937,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* 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, + }; + + static inline void *_wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size, BOOL prio) +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 9dadb6d..b2a5d22 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -1771,15 +1771,16 @@ ULONG CDECL wined3d_surface_decref(struct wined3d_surface *surface) + + void CDECL wined3d_surface_preload(struct wined3d_surface *surface) + { ++ const struct wined3d_device *device = surface->resource.device; + TRACE("surface %p.\n", surface); + +- if (!surface->resource.device->d3d_initialized) ++ if (!device->d3d_initialized) + { + ERR("D3D not initialized.\n"); + return; + } + +- wined3d_texture_preload(surface->container); ++ wined3d_cs_emit_surface_preload(device->cs, surface); + } + + void * CDECL wined3d_surface_get_parent(const struct wined3d_surface *surface) +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index de82b46..409f395 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2654,6 +2654,7 @@ void wined3d_cs_emit_query_destroy(struct wined3d_cs *cs, struct wined3d_query * + void wined3d_cs_emit_update_surface(struct wined3d_cs *cs, struct wined3d_surface *src, + const RECT *src_rect, struct wined3d_surface *dst, const POINT *dst_point) DECLSPEC_HIDDEN; + void wined3d_cs_emit_texture_preload(struct wined3d_cs *cs, struct wined3d_texture *texture) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_surface_preload(struct wined3d_cs *cs, struct wined3d_surface *surface) DECLSPEC_HIDDEN; + + /* 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 +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0098-wined3d-Send-update_texture-calls-through-the-CS.patch b/patches/wined3d-CSMT_Main/0098-wined3d-Send-update_texture-calls-through-the-CS.patch new file mode 100644 index 00000000..cf9ba576 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0098-wined3d-Send-update_texture-calls-through-the-CS.patch @@ -0,0 +1,310 @@ +From ece46da9666f1f33930351ffe5ba81d346db164a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 1 Aug 2013 00:33:48 +0200 +Subject: wined3d: Send update_texture calls through the CS + +--- + dlls/wined3d/cs.c | 33 ++++++++++ + dlls/wined3d/device.c | 134 ++++++++++++++++++----------------------- + dlls/wined3d/wined3d_private.h | 4 ++ + 3 files changed, 97 insertions(+), 74 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 4834dd4..aeba50f 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -72,6 +72,7 @@ enum wined3d_cs_op + WINED3D_CS_OP_UPDATE_SURFACE, + WINED3D_CS_OP_TEXTURE_PRELOAD, + WINED3D_CS_OP_SURFACE_PRELOAD, ++ WINED3D_CS_OP_UPDATE_TEXTURE, + WINED3D_CS_OP_STOP, + }; + +@@ -403,6 +404,12 @@ struct wined3d_cs_surface_preload + struct wined3d_surface *surface; + }; + ++struct wined3d_cs_update_texture ++{ ++ enum wined3d_cs_op opcode; ++ struct wined3d_texture *src, *dst; ++}; ++ + static void wined3d_cs_mt_submit(struct wined3d_cs *cs, size_t size) + { + LONG new_val = (cs->queue.head + size) & (WINED3D_CS_QUEUE_SIZE - 1); +@@ -1888,6 +1895,31 @@ void wined3d_cs_emit_surface_preload(struct wined3d_cs *cs, struct wined3d_surfa + cs->ops->submit(cs, sizeof(*op)); + } + ++static UINT wined3d_cs_exec_update_texture(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_update_texture *op = data; ++ struct wined3d_context *context; ++ ++ context = context_acquire(cs->device, NULL); ++ device_exec_update_texture(context, op->src, op->dst); ++ context_release(context); ++ ++ return sizeof(*op); ++} ++ ++void wined3d_cs_emit_update_texture(struct wined3d_cs *cs, struct wined3d_texture *src, ++ struct wined3d_texture *dst) ++{ ++ struct wined3d_cs_update_texture *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_UPDATE_TEXTURE; ++ op->src = src; ++ op->dst = dst; ++ ++ cs->ops->submit(cs, sizeof(*op)); ++} ++ + static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = + { + /* WINED3D_CS_OP_NOP */ wined3d_cs_exec_nop, +@@ -1938,6 +1970,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* 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, + }; + + static inline void *_wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size, BOOL prio) +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index ed055f8..f1c284a 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -3398,16 +3398,15 @@ void CDECL wined3d_device_draw_indexed_primitive_instanced(struct wined3d_device + } + + /* This is a helper function for UpdateTexture, there is no UpdateVolume method in D3D. */ +-static HRESULT device_update_volume(struct wined3d_device *device, ++static HRESULT device_update_volume(struct wined3d_context *context, + struct wined3d_volume *src_volume, struct wined3d_volume *dst_volume) + { + struct wined3d_map_desc src; + HRESULT hr; + struct wined3d_bo_address data; +- struct wined3d_context *context; + +- TRACE("device %p, src_volume %p, dst_volume %p.\n", +- device, src_volume, dst_volume); ++ TRACE("src_volume %p, dst_volume %p.\n", ++ src_volume, dst_volume); + + if (src_volume->resource.format != dst_volume->resource.format) + { +@@ -3425,8 +3424,6 @@ static HRESULT device_update_volume(struct wined3d_device *device, + if (FAILED(hr = wined3d_volume_map(src_volume, &src, NULL, WINED3D_MAP_READONLY))) + return hr; + +- context = context_acquire(device, NULL); +- + /* Only a prepare, since we're uploading the entire volume. */ + wined3d_texture_prepare_texture(dst_volume->container, context, FALSE); + +@@ -3435,68 +3432,21 @@ static HRESULT device_update_volume(struct wined3d_device *device, + wined3d_volume_upload_data(dst_volume, context, &data); + wined3d_resource_invalidate_location(&dst_volume->resource, ~WINED3D_LOCATION_TEXTURE_RGB); + +- context_release(context); +- + hr = wined3d_volume_unmap(src_volume); + + return hr; + } + +-HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device, +- struct wined3d_texture *src_texture, struct wined3d_texture *dst_texture) ++/* Context activation is done by the caller */ ++void device_exec_update_texture(struct wined3d_context *context, struct wined3d_texture *src_texture, ++ struct wined3d_texture *dst_texture) + { +- enum wined3d_resource_type type; +- unsigned int level_count, i; +- HRESULT hr; +- struct wined3d_context *context; +- +- TRACE("device %p, src_texture %p, dst_texture %p.\n", device, src_texture, dst_texture); +- +- /* Verify that the source and destination textures are non-NULL. */ +- if (!src_texture || !dst_texture) +- { +- WARN("Source and destination textures must be non-NULL, returning WINED3DERR_INVALIDCALL.\n"); +- return WINED3DERR_INVALIDCALL; +- } +- +- if (src_texture->resource.pool != WINED3D_POOL_SYSTEM_MEM) +- { +- WARN("Source texture not in WINED3D_POOL_SYSTEM_MEM, returning WINED3DERR_INVALIDCALL.\n"); +- return WINED3DERR_INVALIDCALL; +- } +- if (dst_texture->resource.pool != WINED3D_POOL_DEFAULT) +- { +- WARN("Destination texture not in WINED3D_POOL_DEFAULT, returning WINED3DERR_INVALIDCALL.\n"); +- return WINED3DERR_INVALIDCALL; +- } +- +- /* Verify that the source and destination textures are the same type. */ +- type = src_texture->resource.type; +- if (dst_texture->resource.type != type) +- { +- WARN("Source and destination have different types, returning WINED3DERR_INVALIDCALL.\n"); +- return WINED3DERR_INVALIDCALL; +- } +- +- /* Check that both textures have the identical numbers of levels. */ +- level_count = wined3d_texture_get_level_count(src_texture); +- if (wined3d_texture_get_level_count(dst_texture) != level_count) +- { +- WARN("Source and destination have different level counts, returning WINED3DERR_INVALIDCALL.\n"); +- return WINED3DERR_INVALIDCALL; +- } +- +- if (wined3d_settings.cs_multithreaded) +- { +- FIXME("Waiting for cs.\n"); +- wined3d_cs_emit_glfinish(device->cs); +- device->cs->ops->finish(device->cs); +- } ++ enum wined3d_resource_type type = src_texture->resource.type; ++ unsigned int level_count = wined3d_texture_get_level_count(src_texture); ++ unsigned int i; + + /* Make sure that the destination texture is loaded. */ +- context = context_acquire(device, NULL); + wined3d_texture_load(dst_texture, context, FALSE); +- context_release(context); + + /* Update every surface level of the texture. */ + switch (type) +@@ -3510,12 +3460,7 @@ HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device, + { + src_surface = surface_from_resource(wined3d_texture_get_sub_resource(src_texture, i)); + dst_surface = surface_from_resource(wined3d_texture_get_sub_resource(dst_texture, i)); +- hr = wined3d_device_update_surface(device, src_surface, NULL, dst_surface, NULL); +- if (FAILED(hr)) +- { +- WARN("Failed to update surface, hr %#x.\n", hr); +- return hr; +- } ++ surface_upload_from_surface(dst_surface, NULL, src_surface, NULL); + } + break; + } +@@ -3529,12 +3474,7 @@ HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device, + { + src_surface = surface_from_resource(wined3d_texture_get_sub_resource(src_texture, i)); + dst_surface = surface_from_resource(wined3d_texture_get_sub_resource(dst_texture, i)); +- hr = wined3d_device_update_surface(device, src_surface, NULL, dst_surface, NULL); +- if (FAILED(hr)) +- { +- WARN("Failed to update surface, hr %#x.\n", hr); +- return hr; +- } ++ surface_upload_from_surface(dst_surface, NULL, src_surface, NULL); + } + break; + } +@@ -3543,13 +3483,14 @@ HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device, + { + for (i = 0; i < level_count; ++i) + { +- hr = device_update_volume(device, ++ HRESULT hr; ++ hr = device_update_volume(context, + volume_from_resource(wined3d_texture_get_sub_resource(src_texture, i)), + volume_from_resource(wined3d_texture_get_sub_resource(dst_texture, i))); + if (FAILED(hr)) + { + WARN("Failed to update volume, hr %#x.\n", hr); +- return hr; ++ return; + } + } + break; +@@ -3557,9 +3498,54 @@ HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device, + + default: + FIXME("Unsupported texture type %#x.\n", type); +- return WINED3DERR_INVALIDCALL; ++ return; ++ } ++} ++ ++HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device, ++ struct wined3d_texture *src_texture, struct wined3d_texture *dst_texture) ++{ ++ enum wined3d_resource_type type; ++ unsigned int level_count; ++ ++ TRACE("device %p, src_texture %p, dst_texture %p.\n", device, src_texture, dst_texture); ++ ++ /* Verify that the source and destination textures are non-NULL. */ ++ if (!src_texture || !dst_texture) ++ { ++ WARN("Source and destination textures must be non-NULL, returning WINED3DERR_INVALIDCALL.\n"); ++ return WINED3DERR_INVALIDCALL; + } + ++ if (src_texture->resource.pool != WINED3D_POOL_SYSTEM_MEM) ++ { ++ WARN("Source texture not in WINED3D_POOL_SYSTEM_MEM, returning WINED3DERR_INVALIDCALL.\n"); ++ return WINED3DERR_INVALIDCALL; ++ } ++ if (dst_texture->resource.pool != WINED3D_POOL_DEFAULT) ++ { ++ WARN("Destination texture not in WINED3D_POOL_DEFAULT, returning WINED3DERR_INVALIDCALL.\n"); ++ return WINED3DERR_INVALIDCALL; ++ } ++ ++ /* Verify that the source and destination textures are the same type. */ ++ type = src_texture->resource.type; ++ if (dst_texture->resource.type != type) ++ { ++ WARN("Source and destination have different types, returning WINED3DERR_INVALIDCALL.\n"); ++ return WINED3DERR_INVALIDCALL; ++ } ++ ++ /* Check that both textures have the identical numbers of levels. */ ++ level_count = wined3d_texture_get_level_count(src_texture); ++ if (wined3d_texture_get_level_count(dst_texture) != level_count) ++ { ++ WARN("Source and destination have different level counts, returning WINED3DERR_INVALIDCALL.\n"); ++ return WINED3DERR_INVALIDCALL; ++ } ++ ++ wined3d_cs_emit_update_texture(device->cs, src_texture, dst_texture); ++ + return WINED3D_OK; + } + +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 409f395..25fce7f 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2063,6 +2063,8 @@ void device_resource_add(struct wined3d_device *device, struct wined3d_resource + void device_resource_released(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN; + 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, ++ struct wined3d_texture *dst_texture) DECLSPEC_HIDDEN; + + static inline BOOL isStateDirty(const struct wined3d_context *context, DWORD state) + { +@@ -2655,6 +2657,8 @@ void wined3d_cs_emit_update_surface(struct wined3d_cs *cs, struct wined3d_surfac + const RECT *src_rect, struct wined3d_surface *dst, const POINT *dst_point) DECLSPEC_HIDDEN; + void wined3d_cs_emit_texture_preload(struct wined3d_cs *cs, struct wined3d_texture *texture) DECLSPEC_HIDDEN; + void wined3d_cs_emit_surface_preload(struct wined3d_cs *cs, struct wined3d_surface *surface) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_update_texture(struct wined3d_cs *cs, struct wined3d_texture *src, ++ struct wined3d_texture *dst) DECLSPEC_HIDDEN; + + /* 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 +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0099-wined3d-Get-rid-of-the-surface_upload_data-glFinish.patch b/patches/wined3d-CSMT_Main/0099-wined3d-Get-rid-of-the-surface_upload_data-glFinish.patch new file mode 100644 index 00000000..f136e2ad --- /dev/null +++ b/patches/wined3d-CSMT_Main/0099-wined3d-Get-rid-of-the-surface_upload_data-glFinish.patch @@ -0,0 +1,27 @@ +From 37bbd4699a2266175bd1344b006d8bd5f352b8b5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 1 Aug 2013 01:43:35 +0200 +Subject: wined3d: Get rid of the surface_upload_data glFinish + +--- + dlls/wined3d/surface.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index b2a5d22..b19355c 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -1403,9 +1403,7 @@ static void surface_upload_data(struct wined3d_surface *surface, const struct wi + checkGLcall("glBindBufferARB"); + } + +- if (wined3d_settings.cs_multithreaded) +- gl_info->gl_ops.gl.p_glFinish(); +- else if (wined3d_settings.strict_draw_ordering) ++ if (wined3d_settings.strict_draw_ordering) + gl_info->gl_ops.gl.p_glFlush(); + + if (gl_info->quirks & WINED3D_QUIRK_FBO_TEX_UPDATE) +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0100-wined3d-Don-t-lock-the-src-volume-in-device_update_v.patch b/patches/wined3d-CSMT_Main/0100-wined3d-Don-t-lock-the-src-volume-in-device_update_v.patch new file mode 100644 index 00000000..260601c8 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0100-wined3d-Don-t-lock-the-src-volume-in-device_update_v.patch @@ -0,0 +1,50 @@ +From b78bd76d80ff1d2edf5a9789e117ae003ec2c842 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 29 Aug 2013 22:25:14 +0200 +Subject: wined3d: Don't lock the src volume in device_update_volume + +This will attempt to wait for the CS, but this code is executed by the CS, so +it will, among other problems, break the single producer, single consumer +assumption of the work queue. + +FIXME: Maybe merge this with the previous patch or change their order. +--- + dlls/wined3d/device.c | 10 +--------- + 1 file changed, 1 insertion(+), 9 deletions(-) + +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index f1c284a..ae7ad31 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -3401,7 +3401,6 @@ void CDECL wined3d_device_draw_indexed_primitive_instanced(struct wined3d_device + static HRESULT device_update_volume(struct wined3d_context *context, + struct wined3d_volume *src_volume, struct wined3d_volume *dst_volume) + { +- struct wined3d_map_desc src; + HRESULT hr; + struct wined3d_bo_address data; + +@@ -3421,19 +3420,12 @@ static HRESULT device_update_volume(struct wined3d_context *context, + return WINED3DERR_INVALIDCALL; + } + +- if (FAILED(hr = wined3d_volume_map(src_volume, &src, NULL, WINED3D_MAP_READONLY))) +- return hr; +- + /* Only a prepare, since we're uploading the entire volume. */ + wined3d_texture_prepare_texture(dst_volume->container, context, FALSE); +- +- data.buffer_object = 0; +- data.addr = src.data; ++ wined3d_resource_get_memory(&src_volume->resource, src_volume->resource.map_binding, &data); + wined3d_volume_upload_data(dst_volume, context, &data); + wined3d_resource_invalidate_location(&dst_volume->resource, ~WINED3D_LOCATION_TEXTURE_RGB); + +- hr = wined3d_volume_unmap(src_volume); +- + return hr; + } + +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0101-wined3d-Handle-evit_managed_resources-through-the-CS.patch b/patches/wined3d-CSMT_Main/0101-wined3d-Handle-evit_managed_resources-through-the-CS.patch new file mode 100644 index 00000000..f4525c92 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0101-wined3d-Handle-evit_managed_resources-through-the-CS.patch @@ -0,0 +1,129 @@ +From 87f659571c4214fcc73a42a1e112d6bda34950a3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Tue, 6 Aug 2013 13:50:31 +0200 +Subject: wined3d: Handle evit_managed_resources through the CS + +--- + dlls/wined3d/cs.c | 37 +++++++++++++++++++++++++++++++++++++ + dlls/wined3d/device.c | 14 +++----------- + dlls/wined3d/wined3d_private.h | 1 + + 3 files changed, 41 insertions(+), 11 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index aeba50f..11aa133 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -73,6 +73,7 @@ enum wined3d_cs_op + WINED3D_CS_OP_TEXTURE_PRELOAD, + WINED3D_CS_OP_SURFACE_PRELOAD, + WINED3D_CS_OP_UPDATE_TEXTURE, ++ WINED3D_CS_OP_EVICT_RESOURCE, + WINED3D_CS_OP_STOP, + }; + +@@ -410,6 +411,12 @@ struct wined3d_cs_update_texture + struct wined3d_texture *src, *dst; + }; + ++struct wined3d_cs_evict_resource ++{ ++ enum wined3d_cs_op opcode; ++ struct wined3d_resource *resource; ++}; ++ + static void wined3d_cs_mt_submit(struct wined3d_cs *cs, size_t size) + { + LONG new_val = (cs->queue.head + size) & (WINED3D_CS_QUEUE_SIZE - 1); +@@ -1920,6 +1927,35 @@ void wined3d_cs_emit_update_texture(struct wined3d_cs *cs, struct wined3d_textur + cs->ops->submit(cs, sizeof(*op)); + } + ++static UINT wined3d_cs_exec_evict_resource(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_evict_resource *op = data; ++ struct wined3d_resource *resource = op->resource; ++ ++ resource->resource_ops->resource_unload(resource); ++ ++ /* FIXME: Is this necessary? Bound buffers are preloaded anyway, and in theory ++ * PreLoad should take care of invalidating the state if the VBO changes */ ++ if (resource->bind_count && resource->type == WINED3D_RTYPE_BUFFER) ++ { ++ device_invalidate_state(cs->device, STATE_STREAMSRC); ++ device_invalidate_state(cs->device, STATE_INDEXBUFFER); ++ } ++ ++ return sizeof(*op); ++} ++ ++void wined3d_cs_emit_evict_resource(struct wined3d_cs *cs, struct wined3d_resource *resource) ++{ ++ struct wined3d_cs_evict_resource *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_EVICT_RESOURCE; ++ op->resource = resource; ++ ++ cs->ops->submit(cs, sizeof(*op)); ++} ++ + static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = + { + /* WINED3D_CS_OP_NOP */ wined3d_cs_exec_nop, +@@ -1971,6 +2007,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* 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, + }; + + static inline void *_wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size, BOOL prio) +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index ae7ad31..f062e84 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -4207,13 +4207,8 @@ void CDECL wined3d_device_evict_managed_resources(struct wined3d_device *device) + + TRACE("device %p.\n", device); + +- if (wined3d_settings.cs_multithreaded) +- { +- FIXME("Waiting for cs.\n"); +- wined3d_cs_emit_glfinish(device->cs); +- device->cs->ops->finish(device->cs); +- } +- ++ /* The resource list is manged by the main thread, iterate here and emit commands for ++ * each resource */ + LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &device->resources, struct wined3d_resource, resource_list_entry) + { + TRACE("Checking resource %p for eviction.\n", resource); +@@ -4221,12 +4216,9 @@ void CDECL wined3d_device_evict_managed_resources(struct wined3d_device *device) + if (resource->pool == WINED3D_POOL_MANAGED && !resource->map_count) + { + TRACE("Evicting %p.\n", resource); +- resource->resource_ops->resource_unload(resource); ++ wined3d_cs_emit_evict_resource(device->cs, resource); + } + } +- +- /* Invalidate stream sources, the buffer(s) may have been evicted. */ +- device_invalidate_state(device, STATE_STREAMSRC); + } + + static void delete_opengl_contexts(struct wined3d_device *device, struct wined3d_swapchain *swapchain) +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 25fce7f..b9eee2c 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2659,6 +2659,7 @@ void wined3d_cs_emit_texture_preload(struct wined3d_cs *cs, struct wined3d_textu + void wined3d_cs_emit_surface_preload(struct wined3d_cs *cs, struct wined3d_surface *surface) DECLSPEC_HIDDEN; + void wined3d_cs_emit_update_texture(struct wined3d_cs *cs, struct wined3d_texture *src, + struct wined3d_texture *dst) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_evict_resource(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN; + + /* 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 +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0102-wined3d-Send-flips-through-the-command-stream.patch b/patches/wined3d-CSMT_Main/0102-wined3d-Send-flips-through-the-command-stream.patch new file mode 100644 index 00000000..5d7c9415 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0102-wined3d-Send-flips-through-the-command-stream.patch @@ -0,0 +1,115 @@ +From 883b523131797cfb6e3c715ff8018850d48734a6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Tue, 6 Aug 2013 17:39:26 +0200 +Subject: wined3d: Send flips through the command stream + +TODO: This remove this patch and flip_surface / surface_flip. +--- + dlls/wined3d/surface.c | 77 ------------------------------------------ + dlls/wined3d/wined3d_private.h | 2 +- + 2 files changed, 1 insertion(+), 78 deletions(-) + +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index b19355c..0c3313d 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -2758,83 +2758,6 @@ void surface_prepare_rb(struct wined3d_surface *surface, const struct wined3d_gl + } + } + +-void flip_surface(struct wined3d_surface *front, struct wined3d_surface *back) +-{ +- if (front->container->level_count != 1 || front->container->layer_count != 1 +- || back->container->level_count != 1 || back->container->layer_count != 1) +- ERR("Flip between surfaces %p and %p not supported.\n", front, back); +- +- /* Flip the surface contents */ +- /* Flip the DC */ +- { +- HDC tmp; +- tmp = front->hDC; +- front->hDC = back->hDC; +- back->hDC = tmp; +- } +- +- /* Flip the DIBsection */ +- { +- HBITMAP tmp = front->dib.DIBsection; +- front->dib.DIBsection = back->dib.DIBsection; +- back->dib.DIBsection = tmp; +- } +- +- /* Flip the surface data */ +- { +- void* tmp; +- +- tmp = front->resource.bitmap_data; +- front->resource.bitmap_data = back->resource.bitmap_data; +- back->resource.bitmap_data = tmp; +- +- tmp = front->resource.heap_memory; +- front->resource.heap_memory = back->resource.heap_memory; +- back->resource.heap_memory = tmp; +- } +- +- /* Flip the PBO */ +- { +- GLuint tmp_pbo = front->resource.buffer_object; +- front->resource.buffer_object = back->resource.buffer_object; +- back->resource.buffer_object = tmp_pbo; +- } +- +- /* Flip the opengl texture */ +- { +- GLuint tmp; +- +- tmp = back->container->texture_rgb.name; +- back->container->texture_rgb.name = front->container->texture_rgb.name; +- front->container->texture_rgb.name = tmp; +- +- tmp = back->container->texture_srgb.name; +- back->container->texture_srgb.name = front->container->texture_srgb.name; +- front->container->texture_srgb.name = tmp; +- +- tmp = back->rb_multisample; +- back->rb_multisample = front->rb_multisample; +- front->rb_multisample = tmp; +- +- tmp = back->rb_resolved; +- back->rb_resolved = front->rb_resolved; +- front->rb_resolved = tmp; +- +- resource_unload(&back->resource); +- resource_unload(&front->resource); +- } +- +- { +- DWORD tmp_flags = back->flags; +- back->flags = front->flags; +- front->flags = tmp_flags; +- +- tmp_flags = back->resource.locations; +- back->resource.locations = front->resource.locations; +- front->resource.locations = tmp_flags; +- } +-} +- + /* Does a direct frame buffer -> texture copy. Stretching is done with single + * pixel copy calls. */ + static void fb_copy_to_texture_direct(struct wined3d_surface *dst_surface, struct wined3d_surface *src_surface, +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index b9eee2c..a2bee4d 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2424,7 +2424,7 @@ BOOL surface_check_block_align(struct wined3d_surface *surface, const RECT *rect + + 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; +-void flip_surface(struct wined3d_surface *front, struct wined3d_surface *back) DECLSPEC_HIDDEN; ++void surface_flip(struct wined3d_surface *front, struct wined3d_surface *back) DECLSPEC_HIDDEN; + + /* Surface flags: */ + #define SFLAG_DIBSECTION 0x00000001 /* Has a DIB section attached for GetDC. */ +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0103-wined3d-Introduce-resource-fencing.patch b/patches/wined3d-CSMT_Main/0103-wined3d-Introduce-resource-fencing.patch new file mode 100644 index 00000000..7d33fe1e --- /dev/null +++ b/patches/wined3d-CSMT_Main/0103-wined3d-Introduce-resource-fencing.patch @@ -0,0 +1,99 @@ +From 7c8966629ab3faabae68c46d1cf63e3d42c89c99 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Wed, 20 Aug 2014 18:01:36 +0200 +Subject: wined3d: Introduce resource fencing. + +FIXME: The buffer part doesn't really make sense without dynamic buffer maps. +--- + dlls/wined3d/cs.c | 19 +++++++++++++++++++ + dlls/wined3d/wined3d_private.h | 16 ++++++++++++++++ + 2 files changed, 35 insertions(+) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 11aa133..1197eef 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -575,6 +575,7 @@ static UINT wined3d_cs_exec_draw(struct wined3d_cs *cs, const void *data) + { + const struct wined3d_cs_draw *op = data; + const struct wined3d_gl_info *gl_info = &cs->device->adapter->gl_info; ++ unsigned int i; + + if (op->indexed && !gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX]) + { +@@ -593,6 +594,14 @@ static UINT wined3d_cs_exec_draw(struct wined3d_cs *cs, const void *data) + draw_primitive(cs->device, &cs->state, op->start_idx, op->index_count, + op->start_instance, op->instance_count, op->indexed); + ++ if (op->indexed) ++ wined3d_resource_dec_fence(&cs->state.index_buffer->resource); ++ for (i = 0; i < sizeof(cs->state.streams) / sizeof(*cs->state.streams); i++) ++ { ++ if (cs->state.streams[i].buffer) ++ wined3d_resource_dec_fence(&cs->state.streams[i].buffer->resource); ++ } ++ + return sizeof(*op); + } + +@@ -600,6 +609,8 @@ void wined3d_cs_emit_draw(struct wined3d_cs *cs, UINT start_idx, UINT index_coun + UINT start_instance, UINT instance_count, BOOL indexed) + { + struct wined3d_cs_draw *op; ++ unsigned int i; ++ const struct wined3d_state *state = &cs->device->state; + + op = cs->ops->require_space(cs, sizeof(*op)); + op->opcode = WINED3D_CS_OP_DRAW; +@@ -609,6 +620,14 @@ void wined3d_cs_emit_draw(struct wined3d_cs *cs, UINT start_idx, UINT index_coun + op->instance_count = instance_count; + op->indexed = indexed; + ++ if (indexed) ++ wined3d_resource_inc_fence(&state->index_buffer->resource); ++ for (i = 0; i < sizeof(state->streams) / sizeof(*state->streams); i++) ++ { ++ if (state->streams[i].buffer) ++ wined3d_resource_inc_fence(&state->streams[i].buffer->resource); ++ } ++ + cs->ops->submit(cs, sizeof(*op)); + } + +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index a2bee4d..b4e5679 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2118,6 +2118,7 @@ struct wined3d_resource + UINT custom_row_pitch, custom_slice_pitch; + struct list resource_list_entry; + DWORD locations; ++ LONG access_fence; + + void *parent; + const struct wined3d_parent_ops *parent_ops; +@@ -2171,6 +2172,21 @@ void wined3d_resource_unmap_internal(struct wined3d_resource *resource) DECLSPEC + void wined3d_resource_update_draw_binding(struct wined3d_resource *resource) DECLSPEC_HIDDEN; + void wined3d_resource_validate_location(struct wined3d_resource *resource, DWORD location) DECLSPEC_HIDDEN; + ++static inline void wined3d_resource_inc_fence(struct wined3d_resource *resource) ++{ ++ InterlockedIncrement(&resource->access_fence); ++} ++ ++static inline void wined3d_resource_dec_fence(struct wined3d_resource *resource) ++{ ++ InterlockedDecrement(&resource->access_fence); ++} ++ ++static inline void wined3d_resource_wait_fence(struct wined3d_resource *resource) ++{ ++ while(InterlockedCompareExchange(&resource->access_fence, 0, 0)); ++} ++ + /* Tests show that the start address of resources is 32 byte aligned */ + #define RESOURCE_ALIGNMENT 16 + +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0104-wined3d-Fence-update_texture-and-update_surface-call.patch b/patches/wined3d-CSMT_Main/0104-wined3d-Fence-update_texture-and-update_surface-call.patch new file mode 100644 index 00000000..af7c1b39 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0104-wined3d-Fence-update_texture-and-update_surface-call.patch @@ -0,0 +1,117 @@ +From a83b0e8543213b11848897ea954412ac0f06083a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Fri, 30 Aug 2013 10:41:42 +0200 +Subject: wined3d: Fence update_texture and update_surface calls + +--- + dlls/wined3d/cs.c | 26 ++++++++++++++++++++++++++ + dlls/wined3d/resource.c | 28 ++++++++++++++++++++++++++++ + 2 files changed, 54 insertions(+) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 1197eef..9a7e6df 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -1844,6 +1844,16 @@ static UINT wined3d_cs_exec_update_surface(struct wined3d_cs *cs, const void *da + surface_upload_from_surface(op->dst, op->has_dst_point ? &op->dst_point : NULL, + op->src, op->has_src_rect ? &op->src_rect : NULL); + ++ if (op->src->container) ++ wined3d_resource_dec_fence(&op->src->container->resource); ++ else ++ wined3d_resource_inc_fence(&op->src->resource); ++ ++ if (op->dst->container) ++ wined3d_resource_dec_fence(&op->dst->container->resource); ++ else ++ wined3d_resource_inc_fence(&op->dst->resource); ++ + return sizeof(*op); + } + +@@ -1871,6 +1881,16 @@ void wined3d_cs_emit_update_surface(struct wined3d_cs *cs, struct wined3d_surfac + op->dst_point = *dst_point; + } + ++ if (src->container) ++ wined3d_resource_inc_fence(&src->container->resource); ++ else ++ wined3d_resource_inc_fence(&src->resource); ++ ++ if (dst->container) ++ wined3d_resource_inc_fence(&dst->container->resource); ++ else ++ wined3d_resource_inc_fence(&dst->resource); ++ + cs->ops->submit(cs, sizeof(*op)); + } + +@@ -1930,6 +1950,9 @@ static UINT wined3d_cs_exec_update_texture(struct wined3d_cs *cs, const void *da + device_exec_update_texture(context, op->src, op->dst); + context_release(context); + ++ wined3d_resource_dec_fence(&op->src->resource); ++ wined3d_resource_dec_fence(&op->dst->resource); ++ + return sizeof(*op); + } + +@@ -1943,6 +1966,9 @@ void wined3d_cs_emit_update_texture(struct wined3d_cs *cs, struct wined3d_textur + op->src = src; + op->dst = dst; + ++ wined3d_resource_inc_fence(&op->src->resource); ++ wined3d_resource_inc_fence(&op->dst->resource); ++ + cs->ops->submit(cs, sizeof(*op)); + } + +diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c +index af60d51..708b080 100644 +--- a/dlls/wined3d/resource.c ++++ b/dlls/wined3d/resource.c +@@ -712,6 +712,32 @@ void *wined3d_resource_map_internal(struct wined3d_resource *resource, DWORD fla + return mem; + } + ++static void wined3d_resource_sync(struct wined3d_resource *resource) ++{ ++ struct wined3d_resource *real_res = resource; ++ struct wined3d_surface *surface; ++ struct wined3d_volume *volume; ++ ++ switch (resource->type) ++ { ++ case WINED3D_RTYPE_SURFACE: ++ surface = surface_from_resource(resource); ++ if (surface->container) ++ real_res = &surface->container->resource; ++ break; ++ ++ case WINED3D_RTYPE_VOLUME: ++ volume = volume_from_resource(resource); ++ real_res = &volume->container->resource; ++ break; ++ ++ default: ++ break; ++ } ++ if (!real_res->access_fence) ++ FIXME("Waiting for CS even though resource %p is idle.\n", resource); ++} ++ + HRESULT wined3d_resource_map(struct wined3d_resource *resource, + struct wined3d_map_desc *map_desc, const struct wined3d_box *box, DWORD flags) + { +@@ -730,6 +756,8 @@ HRESULT wined3d_resource_map(struct wined3d_resource *resource, + + flags = wined3d_resource_sanitize_map_flags(resource, flags); + ++ wined3d_resource_sync(resource); ++ + base_memory = wined3d_cs_emit_resource_map(device->cs, resource, flags); + if (!base_memory) + { +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0105-wined3d-Dirtify-resources-on-unmap.patch b/patches/wined3d-CSMT_Main/0105-wined3d-Dirtify-resources-on-unmap.patch new file mode 100644 index 00000000..8692eafa --- /dev/null +++ b/patches/wined3d-CSMT_Main/0105-wined3d-Dirtify-resources-on-unmap.patch @@ -0,0 +1,81 @@ +From 440a516b0908c7282e89fe73a788ca461d90d81e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 26 Sep 2013 17:25:01 +0200 +Subject: wined3d: Dirtify resources on unmap + +--- + dlls/wined3d/resource.c | 7 ++++++- + dlls/wined3d/surface.c | 4 ++++ + dlls/wined3d/volume.c | 3 +++ + dlls/wined3d/wined3d_private.h | 1 + + 4 files changed, 14 insertions(+), 1 deletion(-) + +diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c +index 708b080..73011f8 100644 +--- a/dlls/wined3d/resource.c ++++ b/dlls/wined3d/resource.c +@@ -806,7 +806,7 @@ HRESULT wined3d_resource_map(struct wined3d_resource *resource, + } + + if (!(flags & (WINED3D_MAP_NO_DIRTY_UPDATE | WINED3D_MAP_READONLY))) +- wined3d_resource_invalidate_location(resource, ~resource->map_binding); ++ resource->unmap_dirtify = TRUE; + + resource->map_count++; + +@@ -826,6 +826,11 @@ void wined3d_resource_unmap_internal(struct wined3d_resource *resource) + wined3d_resource_release_map_ptr(resource, context); + if (context) + context_release(context); ++ ++ if (resource->unmap_dirtify) ++ wined3d_resource_invalidate_location(resource, ~resource->map_binding); ++ resource->unmap_dirtify = FALSE; ++ + } + + HRESULT wined3d_resource_unmap(struct wined3d_resource *resource) +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 0c3313d..e661494 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -2405,6 +2405,10 @@ HRESULT CDECL wined3d_surface_unmap(struct wined3d_surface *surface) + HRESULT hr; + TRACE("surface %p.\n", surface); + ++ if (surface->resource.unmap_dirtify && surface->container) ++ wined3d_texture_set_dirty(surface->container); ++ ++ + hr = wined3d_resource_unmap(&surface->resource); + if (FAILED(hr)) + return hr; +diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c +index 7ce5331..faadea1 100644 +--- a/dlls/wined3d/volume.c ++++ b/dlls/wined3d/volume.c +@@ -424,6 +424,9 @@ HRESULT CDECL wined3d_volume_unmap(struct wined3d_volume *volume) + { + HRESULT hr; + ++ if (volume->resource.unmap_dirtify) ++ wined3d_texture_set_dirty(volume->container); ++ + hr = wined3d_resource_unmap(&volume->resource); + if (hr == WINEDDERR_NOTLOCKED) + return WINED3DERR_INVALIDCALL; +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index b4e5679..d670fe1 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2119,6 +2119,7 @@ struct wined3d_resource + struct list resource_list_entry; + DWORD locations; + LONG access_fence; ++ BOOL unmap_dirtify; + + void *parent; + const struct wined3d_parent_ops *parent_ops; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0106-wined3d-Fence-texture-reads-in-draws.patch b/patches/wined3d-CSMT_Main/0106-wined3d-Fence-texture-reads-in-draws.patch new file mode 100644 index 00000000..50a07edb --- /dev/null +++ b/patches/wined3d-CSMT_Main/0106-wined3d-Fence-texture-reads-in-draws.patch @@ -0,0 +1,53 @@ +From 2d87f930869bcd32273e722a50a13a9330ce6a30 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Fri, 30 Aug 2013 22:42:33 +0200 +Subject: wined3d: Fence texture reads in draws + +This is probably stricter than necessary. GL BOs and allocated sysmem +are just staging resources. After they have been uploaded into the GL +texture, it's in theory OK to write new data buffer without interfering +with old draws. However, it is impossible to tell when if data has been +transfered into the texture because texture loads are delayed until draw +time. Specifically, it is difficult to separate two consecutive maps +from a map, draw, map sequence, where the draw hasn't been executed by +the time the second map occurs. + +The other problem is that sRGB may cause a texture load from +buffer/sysmem even though the GL texture is thought to be loaded. This +is limited to situations where sRGB textures are supported, but +sRGB_decode isn't. +--- + dlls/wined3d/cs.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 9a7e6df..0277a1e 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -601,6 +601,11 @@ static UINT wined3d_cs_exec_draw(struct wined3d_cs *cs, const void *data) + if (cs->state.streams[i].buffer) + wined3d_resource_dec_fence(&cs->state.streams[i].buffer->resource); + } ++ for (i = 0; i < sizeof(cs->state.textures) / sizeof(*cs->state.textures); i++) ++ { ++ if (cs->state.textures[i]) ++ wined3d_resource_dec_fence(&cs->state.textures[i]->resource); ++ } + + return sizeof(*op); + } +@@ -627,6 +632,11 @@ void wined3d_cs_emit_draw(struct wined3d_cs *cs, UINT start_idx, UINT index_coun + if (state->streams[i].buffer) + wined3d_resource_inc_fence(&state->streams[i].buffer->resource); + } ++ for (i = 0; i < sizeof(state->textures) / sizeof(*state->textures); i++) ++ { ++ if (state->textures[i]) ++ wined3d_resource_inc_fence(&state->textures[i]->resource); ++ } + + cs->ops->submit(cs, sizeof(*op)); + } +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0107-wined3d-Fence-render-targets-and-depth-stencils.patch b/patches/wined3d-CSMT_Main/0107-wined3d-Fence-render-targets-and-depth-stencils.patch new file mode 100644 index 00000000..36bdd8e6 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0107-wined3d-Fence-render-targets-and-depth-stencils.patch @@ -0,0 +1,75 @@ +From 093a05f4ff44d45e81e9e0f3dada8fb6551cf382 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Fri, 27 Sep 2013 16:55:58 +0200 +Subject: wined3d: Fence render targets and depth stencils + +--- + dlls/wined3d/cs.c | 38 ++++++++++++++++++++++++++++++++++++++ + 1 file changed, 38 insertions(+) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 0277a1e..a4b996e 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -571,6 +571,30 @@ void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT * + cs->ops->submit(cs, size); + } + ++static inline BOOL wined3d_cs_colorwrite_enabled(const struct wined3d_state *state, unsigned int i) ++{ ++ switch (i) ++ { ++ case 0: ++ return !!state->render_states[WINED3D_RS_COLORWRITEENABLE]; ++ case 1: ++ return !!state->render_states[WINED3D_RS_COLORWRITEENABLE1]; ++ case 2: ++ return !!state->render_states[WINED3D_RS_COLORWRITEENABLE2]; ++ case 3: ++ return !!state->render_states[WINED3D_RS_COLORWRITEENABLE3]; ++ default: ++ ERR("Unexpected color target %u.\n", i); ++ return TRUE; ++ } ++} ++ ++static inline BOOL wined3d_cs_depth_stencil_enabled(const struct wined3d_state *state) ++{ ++ return state->render_states[WINED3D_RS_ZENABLE] ++ || state->render_states[WINED3D_RS_STENCILENABLE]; ++} ++ + static UINT wined3d_cs_exec_draw(struct wined3d_cs *cs, const void *data) + { + const struct wined3d_cs_draw *op = data; +@@ -606,6 +630,13 @@ static UINT wined3d_cs_exec_draw(struct wined3d_cs *cs, const void *data) + if (cs->state.textures[i]) + wined3d_resource_dec_fence(&cs->state.textures[i]->resource); + } ++ for (i = 0; i < sizeof(cs->state.fb.render_targets) / sizeof(*cs->state.fb.render_targets); i++) ++ { ++ if (cs->state.fb.render_targets[i] && wined3d_cs_colorwrite_enabled(&cs->state, i)) ++ wined3d_resource_dec_fence(cs->state.fb.render_targets[i]->resource); ++ } ++ if (cs->state.fb.depth_stencil && wined3d_cs_depth_stencil_enabled(&cs->state)) ++ wined3d_resource_dec_fence(cs->state.fb.depth_stencil->resource); + + return sizeof(*op); + } +@@ -637,6 +668,13 @@ void wined3d_cs_emit_draw(struct wined3d_cs *cs, UINT start_idx, UINT index_coun + if (state->textures[i]) + wined3d_resource_inc_fence(&state->textures[i]->resource); + } ++ for (i = 0; i < sizeof(state->fb.render_targets) / sizeof(*state->fb.render_targets); i++) ++ { ++ if (state->fb.render_targets[i] && wined3d_cs_colorwrite_enabled(state, i)) ++ wined3d_resource_inc_fence(state->fb.render_targets[i]->resource); ++ } ++ if (state->fb.depth_stencil && wined3d_cs_depth_stencil_enabled(state)) ++ wined3d_resource_inc_fence(state->fb.depth_stencil->resource); + + cs->ops->submit(cs, sizeof(*op)); + } +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0108-wined3d-Fence-blit-operations.patch b/patches/wined3d-CSMT_Main/0108-wined3d-Fence-blit-operations.patch new file mode 100644 index 00000000..76d75ed6 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0108-wined3d-Fence-blit-operations.patch @@ -0,0 +1,38 @@ +From 5903d5d7db4ffbfb87d1b9616d13ea05d19dd171 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Fri, 27 Sep 2013 16:57:01 +0200 +Subject: wined3d: Fence blit operations. + +--- + dlls/wined3d/cs.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index a4b996e..5603a37 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -1709,6 +1709,10 @@ static UINT wined3d_cs_exec_blt(struct wined3d_cs *cs, const void *data) + op->src_surface, &op->src_rect, + op->flags, &op->fx, op->filter); + ++ wined3d_resource_dec_fence(&op->dst_surface->container->resource); ++ if (op->src_surface && op->src_surface != op->dst_surface) ++ wined3d_resource_dec_fence(&op->src_surface->container->resource); ++ + return sizeof(*op); + } + +@@ -1730,6 +1734,10 @@ void wined3d_cs_emit_blt(struct wined3d_cs *cs, struct wined3d_surface *dst_surf + if (fx) + op->fx = *fx; + ++ wined3d_resource_inc_fence(&dst_surface->container->resource); ++ if (src_surface && src_surface != dst_surface) ++ wined3d_resource_inc_fence(&src_surface->container->resource); ++ + cs->ops->submit(cs, sizeof(*op)); + } + +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0109-wined3d-Fence-color_fill-operations.patch b/patches/wined3d-CSMT_Main/0109-wined3d-Fence-color_fill-operations.patch new file mode 100644 index 00000000..480e16f8 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0109-wined3d-Fence-color_fill-operations.patch @@ -0,0 +1,34 @@ +From 97f6ef9c0d1d05efc640183d3b045296bca762a0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Fri, 27 Sep 2013 16:58:13 +0200 +Subject: wined3d: Fence color_fill operations. + +--- + dlls/wined3d/cs.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 5603a37..fb92286 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -1750,6 +1750,8 @@ static UINT wined3d_cs_exec_clear_rtv(struct wined3d_cs *cs, const void *data) + + surface_color_fill(surface_from_resource(resource), &op->rect, &op->color); + ++ wined3d_resource_dec_fence(op->view->resource); ++ + return sizeof(*op); + } + +@@ -1764,6 +1766,8 @@ void wined3d_cs_emit_clear_rtv(struct wined3d_cs *cs, struct wined3d_rendertarge + op->rect = *rect; + op->color = *color; + ++ wined3d_resource_inc_fence(view->resource); ++ + cs->ops->submit(cs, sizeof(*op)); + } + +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0110-wined3d-Fence-clear-calls.patch b/patches/wined3d-CSMT_Main/0110-wined3d-Fence-clear-calls.patch new file mode 100644 index 00000000..88804282 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0110-wined3d-Fence-clear-calls.patch @@ -0,0 +1,72 @@ +From d95011df395938acfe6f6c7a33f7c5c094e7df83 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Fri, 27 Sep 2013 17:04:47 +0200 +Subject: wined3d: Fence clear calls. + +--- + dlls/wined3d/cs.c | 27 +++++++++++++++++++++++++-- + 1 file changed, 25 insertions(+), 2 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index fb92286..bdb9279 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -540,7 +540,7 @@ static UINT 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; +- unsigned int extra_rects = op->rect_count ? op->rect_count - 1 : 0; ++ unsigned int extra_rects = op->rect_count ? op->rect_count - 1 : 0, i; + + device = cs->device; + wined3d_get_draw_rect(&cs->state, &draw_rect); +@@ -548,6 +548,17 @@ static UINT wined3d_cs_exec_clear(struct wined3d_cs *cs, const void *data) + &cs->state.fb, op->rect_count, op->rect_count ? op->rects : NULL, &draw_rect, op->flags, + &op->color, op->depth, op->stencil); + ++ if (op->flags & WINED3DCLEAR_TARGET) ++ { ++ for (i = 0; i < sizeof(cs->state.fb.render_targets) / sizeof(*cs->state.fb.render_targets); i++) ++ { ++ if (cs->state.fb.render_targets[i]) ++ wined3d_resource_dec_fence(cs->state.fb.render_targets[i]->resource); ++ } ++ } ++ if (op->flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL)) ++ wined3d_resource_dec_fence(cs->state.fb.depth_stencil->resource); ++ + return sizeof(*op) + sizeof(*op->rects) * extra_rects; + } + +@@ -555,8 +566,9 @@ void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT * + DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil) + { + struct wined3d_cs_clear *op; +- unsigned int extra_rects = rect_count ? rect_count - 1 : 0; ++ unsigned int extra_rects = rect_count ? rect_count - 1 : 0, i; + size_t size = sizeof(*op) + sizeof(*op->rects) * extra_rects; ++ const struct wined3d_state *state = &cs->device->state; + + op = cs->ops->require_space(cs, size); + op->opcode = WINED3D_CS_OP_CLEAR; +@@ -568,6 +580,17 @@ void wined3d_cs_emit_clear(struct wined3d_cs *cs, DWORD rect_count, const RECT * + op->depth = depth; + op->stencil = stencil; + ++ if (flags & WINED3DCLEAR_TARGET) ++ { ++ for (i = 0; i < sizeof(state->fb.render_targets) / sizeof(*state->fb.render_targets); i++) ++ { ++ if (state->fb.render_targets[i]) ++ wined3d_resource_inc_fence(state->fb.render_targets[i]->resource); ++ } ++ } ++ if (flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL)) ++ wined3d_resource_inc_fence(state->fb.depth_stencil->resource); ++ + cs->ops->submit(cs, size); + } + +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0111-wined3d-Fence-present-calls.patch b/patches/wined3d-CSMT_Main/0111-wined3d-Fence-present-calls.patch new file mode 100644 index 00000000..912ae054 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0111-wined3d-Fence-present-calls.patch @@ -0,0 +1,54 @@ +From e485302fbcd610c34cf3e664d3d9a588fb7f3a32 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Fri, 27 Sep 2013 17:55:35 +0200 +Subject: wined3d: Fence present calls. + +--- + dlls/wined3d/cs.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index bdb9279..45dc5ce 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -485,6 +485,7 @@ static UINT wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data) + const RECT *src_rect = op->set_data & CS_PRESENT_SRC_RECT ? &op->src_rect : NULL; + const RECT *dst_rect = op->set_data & CS_PRESENT_DST_RECT ? &op->dst_rect : NULL; + const RGNDATA *dirty_region = op->set_data & CS_PRESENT_DIRTY_RGN ? &op->dirty_region : NULL; ++ unsigned int i; + + swapchain = op->swapchain; + wined3d_swapchain_set_window(swapchain, op->dst_window_override); +@@ -495,6 +496,10 @@ static UINT wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data) + + InterlockedDecrement(&cs->pending_presents); + ++ wined3d_resource_dec_fence(&swapchain->front_buffer->resource); ++ for (i = 0; i < swapchain->desc.backbuffer_count; i++) ++ wined3d_resource_dec_fence(&swapchain->back_buffers[i]->resource); ++ + return sizeof(*op); + } + +@@ -504,6 +509,7 @@ void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *sw + { + struct wined3d_cs_present *op; + LONG pending; ++ unsigned int i; + + op = cs->ops->require_space(cs, sizeof(*op)); + op->opcode = WINED3D_CS_OP_PRESENT; +@@ -527,6 +533,10 @@ void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *sw + } + op->flags = flags; + ++ wined3d_resource_inc_fence(&swapchain->front_buffer->resource); ++ for (i = 0; i < swapchain->desc.backbuffer_count; i++) ++ wined3d_resource_inc_fence(&swapchain->back_buffers[i]->resource); ++ + pending = InterlockedIncrement(&cs->pending_presents); + + cs->ops->submit(cs, sizeof(*op)); +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0112-wined3d-Make-resource-maps-and-unmaps-a-priority-com.patch b/patches/wined3d-CSMT_Main/0112-wined3d-Make-resource-maps-and-unmaps-a-priority-com.patch new file mode 100644 index 00000000..d616b8ef --- /dev/null +++ b/patches/wined3d-CSMT_Main/0112-wined3d-Make-resource-maps-and-unmaps-a-priority-com.patch @@ -0,0 +1,80 @@ +From a14049c3703ec2f275f2ce21b45ba4bc32d6021d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Fri, 27 Sep 2013 17:58:25 +0200 +Subject: wined3d: Make resource maps and unmaps a priority command. + +--- + dlls/wined3d/cs.c | 14 +++++--------- + dlls/wined3d/resource.c | 8 ++++++-- + 2 files changed, 11 insertions(+), 11 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 45dc5ce..054c000 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -1819,19 +1819,15 @@ void *wined3d_cs_emit_resource_map(struct wined3d_cs *cs, struct wined3d_resourc + struct wined3d_cs_resource_map *op; + void *ret; + +- op = cs->ops->require_space(cs, sizeof(*op)); ++ op = cs->ops->require_space_prio(cs, sizeof(*op)); + op->opcode = WINED3D_CS_OP_RESOURCE_MAP; + op->resource = resource; + op->flags = flags; + op->mem = &ret; + +- cs->ops->submit(cs, sizeof(*op)); ++ cs->ops->submit_prio(cs, sizeof(*op)); + +- if (flags & (WINED3D_MAP_NOOVERWRITE | WINED3D_MAP_DISCARD)) +- { +- FIXME("Dynamic resource map is inefficient\n"); +- } +- cs->ops->finish(cs); ++ cs->ops->finish_prio(cs); + + return ret; + } +@@ -1850,11 +1846,11 @@ void wined3d_cs_emit_resource_unmap(struct wined3d_cs *cs, struct wined3d_resour + { + struct wined3d_cs_resource_unmap *op; + +- op = cs->ops->require_space(cs, sizeof(*op)); ++ op = cs->ops->require_space_prio(cs, sizeof(*op)); + op->opcode = WINED3D_CS_OP_RESOURCE_UNMAP; + op->resource = resource; + +- cs->ops->submit(cs, sizeof(*op)); ++ cs->ops->submit_prio(cs, sizeof(*op)); + } + + static UINT wined3d_cs_exec_query_issue(struct wined3d_cs *cs, const void *data) +diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c +index 73011f8..d2407a1 100644 +--- a/dlls/wined3d/resource.c ++++ b/dlls/wined3d/resource.c +@@ -734,8 +734,7 @@ static void wined3d_resource_sync(struct wined3d_resource *resource) + default: + break; + } +- if (!real_res->access_fence) +- FIXME("Waiting for CS even though resource %p is idle.\n", resource); ++ wined3d_resource_wait_fence(real_res); + } + + HRESULT wined3d_resource_map(struct wined3d_resource *resource, +@@ -756,6 +755,11 @@ HRESULT wined3d_resource_map(struct wined3d_resource *resource, + + flags = wined3d_resource_sanitize_map_flags(resource, flags); + ++ if (flags & (WINED3D_MAP_NOOVERWRITE | WINED3D_MAP_DISCARD)) ++ { ++ FIXME("Dynamic resource map is inefficient\n"); ++ } ++ + wined3d_resource_sync(resource); + + base_memory = wined3d_cs_emit_resource_map(device->cs, resource, flags); +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0113-wined3d-Dirtify-changed-textures-through-the-command.patch b/patches/wined3d-CSMT_Main/0113-wined3d-Dirtify-changed-textures-through-the-command.patch new file mode 100644 index 00000000..cd8763ad --- /dev/null +++ b/patches/wined3d-CSMT_Main/0113-wined3d-Dirtify-changed-textures-through-the-command.patch @@ -0,0 +1,176 @@ +From eb59e53d03f032fe4e04a6e7843ac06e9dddbbdd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Fri, 27 Sep 2013 18:46:19 +0200 +Subject: wined3d: Dirtify changed textures through the command stream. + +This makes sure unsynchronized maps (NOOVERWRITE /DISCARD) are reflected +in the volume's location flags at the right time. +--- + dlls/wined3d/cs.c | 31 ++++++++++++++++++++++++++++++- + dlls/wined3d/resource.c | 15 ++++++++++----- + dlls/wined3d/surface.c | 9 +++------ + dlls/wined3d/wined3d_private.h | 2 ++ + 4 files changed, 45 insertions(+), 12 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 054c000..f5c10dd 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -65,6 +65,7 @@ enum wined3d_cs_op + WINED3D_CS_OP_SET_LIGHT_ENABLE, + WINED3D_CS_OP_BLT, + WINED3D_CS_OP_CLEAR_RTV, ++ WINED3D_CS_OP_RESOURCE_CHANGED, + WINED3D_CS_OP_RESOURCE_MAP, + WINED3D_CS_OP_RESOURCE_UNMAP, + WINED3D_CS_OP_QUERY_ISSUE, +@@ -365,6 +366,12 @@ struct wined3d_cs_resource_unmap + struct wined3d_resource *resource; + }; + ++struct wined3d_cs_resource_changed ++{ ++ enum wined3d_cs_op opcode; ++ struct wined3d_resource *resource; ++}; ++ + struct wined3d_cs_skip + { + enum wined3d_cs_op opcode; +@@ -1804,6 +1811,27 @@ void wined3d_cs_emit_clear_rtv(struct wined3d_cs *cs, struct wined3d_rendertarge + cs->ops->submit(cs, sizeof(*op)); + } + ++static UINT wined3d_cs_exec_resource_changed(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_resource_changed *op = data; ++ struct wined3d_resource *resource = op->resource; ++ ++ wined3d_resource_changed(resource); ++ ++ return sizeof(*op); ++} ++ ++void wined3d_cs_emit_resource_changed(struct wined3d_cs *cs, struct wined3d_resource *resource) ++{ ++ struct wined3d_cs_resource_changed *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_RESOURCE_CHANGED; ++ op->resource = resource; ++ ++ cs->ops->submit(cs, sizeof(*op)); ++} ++ + static UINT wined3d_cs_exec_resource_map(struct wined3d_cs *cs, const void *data) + { + const struct wined3d_cs_resource_map *op = data; +@@ -2110,11 +2138,11 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* 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_SHADER_RESOURCE_VIEW */ wined3d_cs_exec_set_shader_resource_view, + /* 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, +@@ -2133,6 +2161,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* 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_QUERY_ISSUE */ wined3d_cs_exec_query_issue, +diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c +index d2407a1..7cafdc6 100644 +--- a/dlls/wined3d/resource.c ++++ b/dlls/wined3d/resource.c +@@ -830,11 +830,6 @@ void wined3d_resource_unmap_internal(struct wined3d_resource *resource) + wined3d_resource_release_map_ptr(resource, context); + if (context) + context_release(context); +- +- if (resource->unmap_dirtify) +- wined3d_resource_invalidate_location(resource, ~resource->map_binding); +- resource->unmap_dirtify = FALSE; +- + } + + HRESULT wined3d_resource_unmap(struct wined3d_resource *resource) +@@ -849,7 +844,17 @@ HRESULT wined3d_resource_unmap(struct wined3d_resource *resource) + } + + wined3d_cs_emit_resource_unmap(device->cs, resource); ++ ++ if (resource->unmap_dirtify) ++ wined3d_cs_emit_resource_changed(device->cs, resource); ++ resource->unmap_dirtify = FALSE; ++ + resource->map_count--; + + return WINED3D_OK; + } ++ ++void wined3d_resource_changed(struct wined3d_resource *resource) ++{ ++ wined3d_resource_invalidate_location(resource, ~resource->map_binding); ++} +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index e661494..535e21a 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -1093,6 +1093,9 @@ static void wined3d_surface_location_invalidated(struct wined3d_resource *resour + + if (location & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) + wined3d_texture_set_dirty(surface->container); ++ ++ if (surface->container->swapchain && surface->container == surface->container->swapchain->front_buffer) ++ surface->surface_ops->surface_frontbuffer_updated(surface); + } + + static const struct wined3d_surface_ops surface_ops = +@@ -2405,16 +2408,10 @@ HRESULT CDECL wined3d_surface_unmap(struct wined3d_surface *surface) + HRESULT hr; + TRACE("surface %p.\n", surface); + +- if (surface->resource.unmap_dirtify && surface->container) +- wined3d_texture_set_dirty(surface->container); +- +- + hr = wined3d_resource_unmap(&surface->resource); + if (FAILED(hr)) + return hr; + +- if (surface->container->swapchain && surface->container == surface->container->swapchain->front_buffer) +- surface->surface_ops->surface_frontbuffer_updated(surface); + memset(&surface->lockedRect, 0, sizeof(surface->lockedRect)); + + return hr; +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index d670fe1..b9831fd 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2146,6 +2146,7 @@ HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device * + void resource_unload(struct wined3d_resource *resource) DECLSPEC_HIDDEN; + 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) DECLSPEC_HIDDEN; + BOOL wined3d_resource_check_block_align(const struct wined3d_resource *resource, + const struct wined3d_box *box) DECLSPEC_HIDDEN; + void wined3d_resource_free_bo(struct wined3d_resource *resource) DECLSPEC_HIDDEN; +@@ -2662,6 +2663,7 @@ void wined3d_cs_emit_blt(struct wined3d_cs *cs, struct wined3d_surface *dst_surf + enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN; + void wined3d_cs_emit_clear_rtv(struct wined3d_cs *cs, struct wined3d_rendertarget_view *view, + const RECT *rect, const struct wined3d_color *color) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_resource_changed(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN; + void *wined3d_cs_emit_resource_map(struct wined3d_cs *cs, struct wined3d_resource *resource, + DWORD flags) DECLSPEC_HIDDEN; + void wined3d_cs_emit_resource_unmap(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0114-wined3d-Wrap-GL-BOs-in-a-structure.patch b/patches/wined3d-CSMT_Main/0114-wined3d-Wrap-GL-BOs-in-a-structure.patch new file mode 100644 index 00000000..68d16aad --- /dev/null +++ b/patches/wined3d-CSMT_Main/0114-wined3d-Wrap-GL-BOs-in-a-structure.patch @@ -0,0 +1,269 @@ +From 496e24cd5a0649042e456adc2b4e512e15463974 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Fri, 30 Aug 2013 17:00:35 +0200 +Subject: wined3d: Wrap GL BOs in a structure + +The idea is to use those structures for mapping through the command stream and caching +them for DISCARD maps. +--- + dlls/wined3d/device.c | 53 ++++++++++++++++++++++++++++++++++++++++++ + dlls/wined3d/resource.c | 34 +++++++++++---------------- + dlls/wined3d/surface.c | 6 ++--- + dlls/wined3d/volume.c | 6 ++--- + dlls/wined3d/wined3d_private.h | 15 +++++++++++- + 5 files changed, 86 insertions(+), 28 deletions(-) + +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index f062e84..6f82385 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -5007,3 +5007,56 @@ LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL + else + return CallWindowProcA(proc, window, message, wparam, lparam); + } ++ ++/* Context activation is done by the caller */ ++struct wined3d_gl_bo *wined3d_device_get_bo(struct wined3d_device *device, UINT size, GLenum gl_usage, ++ GLenum type_hint, struct wined3d_context *context) ++{ ++ struct wined3d_gl_bo *ret; ++ const struct wined3d_gl_info *gl_info; ++ ++ TRACE("device %p, size %u, gl_usage %u, type_hint %u\n", device, size, gl_usage, ++ type_hint); ++ ++ ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ret)); ++ if(!ret) ++ return NULL; ++ ret->type_hint = type_hint; ++ ret->size = size; ++ ret->usage = gl_usage; ++ ++ gl_info = context->gl_info; ++ ++ GL_EXTCALL(glGenBuffersARB(1, &ret->name)); ++ if (type_hint == GL_ELEMENT_ARRAY_BUFFER_ARB) ++ context_invalidate_state(context, STATE_INDEXBUFFER); ++ GL_EXTCALL(glBindBufferARB(type_hint, ret->name)); ++ GL_EXTCALL(glBufferDataARB(type_hint, size, NULL, gl_usage)); ++ GL_EXTCALL(glBindBufferARB(type_hint, 0)); ++ checkGLcall("Create buffer object"); ++ ++ TRACE("Successfully created and set up buffer %u\n", ret->name); ++ return ret; ++} ++ ++/* Context activation is done by the caller */ ++static void wined3d_device_destroy_bo(struct wined3d_device *device, const struct wined3d_context *context, ++ struct wined3d_gl_bo *bo) ++{ ++ const struct wined3d_gl_info *gl_info = context->gl_info; ++ TRACE("device %p, bo %p, GL bo %u\n", device, bo, bo->name); ++ ++ GL_EXTCALL(glDeleteBuffersARB(1, &bo->name)); ++ checkGLcall("glDeleteBuffersARB"); ++ ++ HeapFree(GetProcessHeap(), 0, bo); ++} ++ ++/* Context activation is done by the caller */ ++void wined3d_device_release_bo(struct wined3d_device *device, struct wined3d_gl_bo *bo, ++ const struct wined3d_context *context) ++{ ++ TRACE("device %p, bo %p, GL bo %u\n", device, bo, bo->name); ++ ++ wined3d_device_destroy_bo(device, context, bo); ++} +diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c +index 7cafdc6..4fc4ce9 100644 +--- a/dlls/wined3d/resource.c ++++ b/dlls/wined3d/resource.c +@@ -145,12 +145,10 @@ HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device * + void wined3d_resource_free_bo(struct wined3d_resource *resource) + { + struct wined3d_context *context = context_acquire(resource->device, NULL); +- const struct wined3d_gl_info *gl_info = context->gl_info; + +- TRACE("Deleting GL buffer %u belonging to resource %p.\n", resource->buffer_object, resource); +- GL_EXTCALL(glDeleteBuffersARB(1, &resource->buffer_object)); +- checkGLcall("glDeleteBuffersARB"); +- resource->buffer_object = 0; ++ wined3d_device_release_bo(resource->device, resource->buffer, context); ++ resource->buffer = NULL; ++ + context_release(context); + } + +@@ -166,7 +164,7 @@ void resource_cleanup(struct wined3d_resource *resource) + adapter_adjust_memory(resource->device->adapter, (INT64)0 - resource->size); + } + +- if (resource->buffer_object) ++ if (resource->buffer) + wined3d_resource_free_bo(resource); + + wined3d_resource_free_sysmem(resource); +@@ -179,7 +177,7 @@ void resource_unload(struct wined3d_resource *resource) + if (resource->map_count) + ERR("Resource %p is being unloaded while mapped.\n", resource); + +- if (resource->buffer_object) ++ if (resource->buffer) + wined3d_resource_free_bo(resource); + + context_resource_unloaded(resource->device, +@@ -397,7 +395,7 @@ void wined3d_resource_get_memory(const struct wined3d_resource *resource, + { + if (location & WINED3D_LOCATION_BUFFER) + { +- data->buffer_object = resource->buffer_object; ++ data->buffer_object = resource->buffer->name; + data->addr = NULL; + return; + } +@@ -506,7 +504,7 @@ BYTE *wined3d_resource_get_map_ptr(const struct wined3d_resource *resource, + { + case WINED3D_LOCATION_BUFFER: + gl_info = context->gl_info; +- GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, resource->buffer_object)); ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, resource->buffer->name)); + + if (gl_info->supported[ARB_MAP_BUFFER_RANGE]) + { +@@ -549,7 +547,7 @@ void wined3d_resource_release_map_ptr(const struct wined3d_resource *resource, + { + case WINED3D_LOCATION_BUFFER: + gl_info = context->gl_info; +- GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, resource->buffer_object)); ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, resource->buffer->name)); + GL_EXTCALL(glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB)); + GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); + checkGLcall("Unmap GL buffer"); +@@ -567,20 +565,14 @@ void wined3d_resource_release_map_ptr(const struct wined3d_resource *resource, + } + + /* Context activation is done by the caller. */ +-static void wined3d_resource_prepare_bo(struct wined3d_resource *resource, const struct wined3d_context *context) ++static void wined3d_resource_prepare_bo(struct wined3d_resource *resource, struct wined3d_context *context) + { +- const struct wined3d_gl_info *gl_info = context->gl_info; +- +- if (resource->buffer_object) ++ if (resource->buffer) + return; + +- GL_EXTCALL(glGenBuffersARB(1, &resource->buffer_object)); +- GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, resource->buffer_object)); +- GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, resource->size, NULL, GL_STREAM_DRAW_ARB)); +- GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); +- checkGLcall("Create GL buffer"); +- +- TRACE("Created GL buffer %u for resource %p.\n", resource->buffer_object, resource); ++ resource->buffer = wined3d_device_get_bo(resource->device, resource->size, ++ GL_STREAM_DRAW_ARB, GL_PIXEL_UNPACK_BUFFER_ARB, context); ++ TRACE("Created GL buffer %u for resource %p.\n", resource->buffer->name, resource); + } + + BOOL wined3d_resource_prepare_system_memory(struct wined3d_resource *resource) +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 535e21a..7c532f0 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -48,7 +48,7 @@ static void surface_cleanup(struct wined3d_surface *surface) + surface->resource.device->cs->ops->finish(surface->resource.device->cs); + } + +- if (surface->resource.buffer_object || surface->rb_multisample ++ if (surface->resource.buffer || surface->rb_multisample + || surface->rb_resolved || !list_empty(&surface->renderbuffers)) + { + struct wined3d_renderbuffer_entry *entry, *entry2; +@@ -2515,7 +2515,7 @@ HRESULT CDECL wined3d_surface_getdc(struct wined3d_surface *surface, HDC *dc) + } + if (!(surface->resource.map_binding == WINED3D_LOCATION_USER_MEMORY + || surface->container->flags & WINED3D_TEXTURE_PIN_SYSMEM +- || surface->resource.buffer_object)) ++ || surface->resource.buffer)) + surface->resource.map_binding = WINED3D_LOCATION_DIB; + } + +@@ -3880,7 +3880,7 @@ static HRESULT surface_load_texture(struct wined3d_surface *surface, + /* Don't use PBOs for converted surfaces. During PBO conversion we look at + * WINED3D_TEXTURE_CONVERTED but it isn't set (yet) in all cases it is + * getting called. */ +- if ((format.convert || conversion) && surface->resource.buffer_object) ++ if ((format.convert || conversion) && surface->resource.buffer) + { + TRACE("Removing the pbo attached to surface %p.\n", surface); + +diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c +index faadea1..467169f 100644 +--- a/dlls/wined3d/volume.c ++++ b/dlls/wined3d/volume.c +@@ -202,7 +202,7 @@ static void wined3d_volume_load_location(struct wined3d_resource *resource, + } + else if (volume->resource.locations & WINED3D_LOCATION_BUFFER) + { +- struct wined3d_bo_address data = {volume->resource.buffer_object, NULL}; ++ struct wined3d_bo_address data = {volume->resource.buffer->name, NULL}; + wined3d_volume_upload_data(volume, context, &data); + } + else if (volume->resource.locations & WINED3D_LOCATION_TEXTURE_RGB) +@@ -251,12 +251,12 @@ static void wined3d_volume_load_location(struct wined3d_resource *resource, + break; + + case WINED3D_LOCATION_BUFFER: +- if (!volume->resource.buffer_object) ++ if (!volume->resource.buffer) + ERR("Trying to load WINED3D_LOCATION_BUFFER without setting it up first.\n"); + + if (volume->resource.locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) + { +- struct wined3d_bo_address data = {volume->resource.buffer_object, NULL}; ++ struct wined3d_bo_address data = {volume->resource.buffer->name, NULL}; + + if (volume->resource.locations & WINED3D_LOCATION_TEXTURE_RGB) + wined3d_texture_bind_and_dirtify(volume->container, context, FALSE); +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index b9831fd..8477d0c 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -1960,6 +1960,14 @@ struct wined3d_state + DWORD render_states[WINEHIGHEST_RENDER_STATE + 1]; + }; + ++struct wined3d_gl_bo ++{ ++ GLuint name; ++ GLenum usage; ++ GLenum type_hint; ++ UINT size; ++}; ++ + #define WINED3D_UNMAPPED_STAGE ~0U + + /* Multithreaded flag. Removed from the public header to signal that +@@ -2065,6 +2073,11 @@ void device_invalidate_state(const struct wined3d_device *device, DWORD state) D + 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, + struct wined3d_texture *dst_texture) DECLSPEC_HIDDEN; ++struct wined3d_gl_bo *wined3d_device_get_bo(struct wined3d_device *device, UINT size, GLenum gl_usage, ++ GLenum type_hint, struct wined3d_context *context) DECLSPEC_HIDDEN; ++void wined3d_device_release_bo(struct wined3d_device *device, struct wined3d_gl_bo *bo, ++ const struct wined3d_context *context) DECLSPEC_HIDDEN; ++ + + static inline BOOL isStateDirty(const struct wined3d_context *context, DWORD state) + { +@@ -2114,7 +2127,7 @@ struct wined3d_resource + UINT size; + DWORD priority; + void *heap_memory, *user_memory, *bitmap_data; +- GLuint buffer_object; ++ struct wined3d_gl_bo *buffer; + UINT custom_row_pitch, custom_slice_pitch; + struct list resource_list_entry; + DWORD locations; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0115-wined3d-Separate-resource-map-and-draw-buffers.patch b/patches/wined3d-CSMT_Main/0115-wined3d-Separate-resource-map-and-draw-buffers.patch new file mode 100644 index 00000000..47d04901 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0115-wined3d-Separate-resource-map-and-draw-buffers.patch @@ -0,0 +1,69 @@ +From 71bd4bdb1014498b5877d04834bf58413220c408 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Fri, 30 Aug 2013 17:06:29 +0200 +Subject: wined3d: Separate resource map and draw buffers + +--- + dlls/wined3d/resource.c | 9 +++++++-- + dlls/wined3d/wined3d_private.h | 2 +- + 2 files changed, 8 insertions(+), 3 deletions(-) + +diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c +index 4fc4ce9..65e8f55 100644 +--- a/dlls/wined3d/resource.c ++++ b/dlls/wined3d/resource.c +@@ -146,8 +146,12 @@ void wined3d_resource_free_bo(struct wined3d_resource *resource) + { + struct wined3d_context *context = context_acquire(resource->device, NULL); + ++ if (resource->buffer != resource->map_buffer) ++ ERR("Releasing resource buffer with buffer != map_buffer.\n"); ++ + wined3d_device_release_bo(resource->device, resource->buffer, context); + resource->buffer = NULL; ++ resource->map_buffer = NULL; + + context_release(context); + } +@@ -504,7 +508,7 @@ BYTE *wined3d_resource_get_map_ptr(const struct wined3d_resource *resource, + { + case WINED3D_LOCATION_BUFFER: + gl_info = context->gl_info; +- GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, resource->buffer->name)); ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, resource->map_buffer->name)); + + if (gl_info->supported[ARB_MAP_BUFFER_RANGE]) + { +@@ -547,7 +551,7 @@ void wined3d_resource_release_map_ptr(const struct wined3d_resource *resource, + { + case WINED3D_LOCATION_BUFFER: + gl_info = context->gl_info; +- GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, resource->buffer->name)); ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, resource->map_buffer->name)); + GL_EXTCALL(glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB)); + GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); + checkGLcall("Unmap GL buffer"); +@@ -572,6 +576,7 @@ static void wined3d_resource_prepare_bo(struct wined3d_resource *resource, struc + + resource->buffer = wined3d_device_get_bo(resource->device, resource->size, + GL_STREAM_DRAW_ARB, GL_PIXEL_UNPACK_BUFFER_ARB, context); ++ resource->map_buffer = resource->buffer; + TRACE("Created GL buffer %u for resource %p.\n", resource->buffer->name, resource); + } + +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 8477d0c..eb84cbc 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2127,7 +2127,7 @@ struct wined3d_resource + UINT size; + DWORD priority; + void *heap_memory, *user_memory, *bitmap_data; +- struct wined3d_gl_bo *buffer; ++ struct wined3d_gl_bo *buffer, *map_buffer; + UINT custom_row_pitch, custom_slice_pitch; + struct list resource_list_entry; + DWORD locations; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0116-wined3d-Implement-DISCARD-resource-maps-with-buffers.patch b/patches/wined3d-CSMT_Main/0116-wined3d-Implement-DISCARD-resource-maps-with-buffers.patch new file mode 100644 index 00000000..cb561630 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0116-wined3d-Implement-DISCARD-resource-maps-with-buffers.patch @@ -0,0 +1,150 @@ +From fe033b6524bc09e86116176d015a14214735439d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Fri, 27 Sep 2013 19:06:41 +0200 +Subject: wined3d: Implement DISCARD resource maps with buffers. + +--- + dlls/wined3d/cs.c | 7 +++++-- + dlls/wined3d/resource.c | 41 ++++++++++++++++++++++++++++++++++------- + dlls/wined3d/wined3d_private.h | 6 ++++-- + 3 files changed, 43 insertions(+), 11 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index f5c10dd..d86aa59 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -370,6 +370,7 @@ struct wined3d_cs_resource_changed + { + enum wined3d_cs_op opcode; + struct wined3d_resource *resource; ++ struct wined3d_gl_bo *swap_buffer; + }; + + struct wined3d_cs_skip +@@ -1816,18 +1817,20 @@ static UINT wined3d_cs_exec_resource_changed(struct wined3d_cs *cs, const void * + const struct wined3d_cs_resource_changed *op = data; + struct wined3d_resource *resource = op->resource; + +- wined3d_resource_changed(resource); ++ wined3d_resource_changed(resource, op->swap_buffer); + + return sizeof(*op); + } + +-void wined3d_cs_emit_resource_changed(struct wined3d_cs *cs, struct wined3d_resource *resource) ++void wined3d_cs_emit_resource_changed(struct wined3d_cs *cs, struct wined3d_resource *resource, ++ struct wined3d_gl_bo *swap_buffer) + { + struct wined3d_cs_resource_changed *op; + + op = cs->ops->require_space(cs, sizeof(*op)); + op->opcode = WINED3D_CS_OP_RESOURCE_CHANGED; + op->resource = resource; ++ op->swap_buffer = swap_buffer; + + cs->ops->submit(cs, sizeof(*op)); + } +diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c +index 65e8f55..8d9757c 100644 +--- a/dlls/wined3d/resource.c ++++ b/dlls/wined3d/resource.c +@@ -697,9 +697,27 @@ void *wined3d_resource_map_internal(struct wined3d_resource *resource, DWORD fla + } + + if (flags & WINED3D_MAP_DISCARD) ++ { ++ switch (resource->map_binding) ++ { ++ case WINED3D_LOCATION_BUFFER: ++ resource->map_buffer = wined3d_device_get_bo(device, resource->size, ++ GL_STREAM_DRAW_ARB, GL_PIXEL_UNPACK_BUFFER_ARB, context); ++ break; ++ ++ default: ++ if (resource->access_fence) ++ ERR("Location %s does not support DISCARD maps.\n", ++ wined3d_debug_location(resource->map_binding)); ++ if (resource->pool != WINED3D_POOL_DEFAULT) ++ FIXME("Discard used on %s pool resource.\n", debug_d3dpool(resource->pool)); ++ } + wined3d_resource_validate_location(resource, resource->map_binding); ++ } + else ++ { + wined3d_resource_load_location(resource, context, resource->map_binding); ++ } + + mem = wined3d_resource_get_map_ptr(resource, context, flags); + +@@ -752,12 +770,11 @@ HRESULT wined3d_resource_map(struct wined3d_resource *resource, + + flags = wined3d_resource_sanitize_map_flags(resource, flags); + +- if (flags & (WINED3D_MAP_NOOVERWRITE | WINED3D_MAP_DISCARD)) +- { +- FIXME("Dynamic resource map is inefficient\n"); +- } ++ if (flags & WINED3D_MAP_NOOVERWRITE) ++ FIXME("WINED3D_MAP_NOOVERWRITE are not implemented yet.\n"); + +- wined3d_resource_sync(resource); ++ if (!(flags & WINED3D_MAP_DISCARD) || resource->map_binding != WINED3D_LOCATION_BUFFER) ++ wined3d_resource_sync(resource); + + base_memory = wined3d_cs_emit_resource_map(device->cs, resource, flags); + if (!base_memory) +@@ -843,7 +860,7 @@ HRESULT wined3d_resource_unmap(struct wined3d_resource *resource) + wined3d_cs_emit_resource_unmap(device->cs, resource); + + if (resource->unmap_dirtify) +- wined3d_cs_emit_resource_changed(device->cs, resource); ++ wined3d_cs_emit_resource_changed(device->cs, resource, resource->map_buffer); + resource->unmap_dirtify = FALSE; + + resource->map_count--; +@@ -851,7 +868,17 @@ HRESULT wined3d_resource_unmap(struct wined3d_resource *resource) + return WINED3D_OK; + } + +-void wined3d_resource_changed(struct wined3d_resource *resource) ++void wined3d_resource_changed(struct wined3d_resource *resource, struct wined3d_gl_bo *swap_buffer) + { ++ struct wined3d_device *device = resource->device; ++ ++ if (swap_buffer && swap_buffer != resource->buffer) ++ { ++ struct wined3d_context *context = context_acquire(device, NULL); ++ wined3d_device_release_bo(device, resource->buffer, context); ++ context_release(context); ++ resource->buffer = swap_buffer; ++ } ++ + wined3d_resource_invalidate_location(resource, ~resource->map_binding); + } +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index eb84cbc..15d63e2 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2159,7 +2159,8 @@ HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device * + void resource_unload(struct wined3d_resource *resource) DECLSPEC_HIDDEN; + 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) DECLSPEC_HIDDEN; ++void wined3d_resource_changed(struct wined3d_resource *resource, ++ struct wined3d_gl_bo *swap_buffer) DECLSPEC_HIDDEN; + BOOL wined3d_resource_check_block_align(const struct wined3d_resource *resource, + const struct wined3d_box *box) DECLSPEC_HIDDEN; + void wined3d_resource_free_bo(struct wined3d_resource *resource) DECLSPEC_HIDDEN; +@@ -2676,7 +2677,8 @@ void wined3d_cs_emit_blt(struct wined3d_cs *cs, struct wined3d_surface *dst_surf + enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN; + void wined3d_cs_emit_clear_rtv(struct wined3d_cs *cs, struct wined3d_rendertarget_view *view, + const RECT *rect, const struct wined3d_color *color) DECLSPEC_HIDDEN; +-void wined3d_cs_emit_resource_changed(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_resource_changed(struct wined3d_cs *cs, struct wined3d_resource *resource, ++ struct wined3d_gl_bo *swap_buffer) DECLSPEC_HIDDEN; + void *wined3d_cs_emit_resource_map(struct wined3d_cs *cs, struct wined3d_resource *resource, + DWORD flags) DECLSPEC_HIDDEN; + void wined3d_cs_emit_resource_unmap(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0117-wined3d-Implement-DISCARD-resource-maps-with-heap-me.patch b/patches/wined3d-CSMT_Main/0117-wined3d-Implement-DISCARD-resource-maps-with-heap-me.patch new file mode 100644 index 00000000..fe1a38ea --- /dev/null +++ b/patches/wined3d-CSMT_Main/0117-wined3d-Implement-DISCARD-resource-maps-with-heap-me.patch @@ -0,0 +1,258 @@ +From 2483911906a4adfe52afe00f061cd473a2b7ec5b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Fri, 27 Sep 2013 19:24:21 +0200 +Subject: wined3d: Implement DISCARD resource maps with heap memory. + +--- + dlls/wined3d/buffer.c | 1 + + dlls/wined3d/cs.c | 6 ++++-- + dlls/wined3d/resource.c | 40 +++++++++++++++++++++++++++++++++++----- + dlls/wined3d/surface.c | 3 +++ + dlls/wined3d/volume.c | 2 ++ + dlls/wined3d/wined3d_private.h | 6 +++--- + 6 files changed, 48 insertions(+), 10 deletions(-) + +diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c +index b76a07d..3ca1143 100644 +--- a/dlls/wined3d/buffer.c ++++ b/dlls/wined3d/buffer.c +@@ -493,6 +493,7 @@ BYTE *buffer_get_sysmem(struct wined3d_buffer *This, struct wined3d_context *con + + if (!wined3d_resource_allocate_sysmem(&This->resource)) + ERR("Failed to allocate system memory.\n"); ++ This->resource.heap_memory = This->resource.map_heap_memory; + + if (This->buffer_type_hint == GL_ELEMENT_ARRAY_BUFFER_ARB) + context_invalidate_state(context, STATE_INDEXBUFFER); +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index d86aa59..9307246 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -371,6 +371,7 @@ struct wined3d_cs_resource_changed + enum wined3d_cs_op opcode; + struct wined3d_resource *resource; + struct wined3d_gl_bo *swap_buffer; ++ void *swap_heap_memory; + }; + + struct wined3d_cs_skip +@@ -1817,13 +1818,13 @@ static UINT wined3d_cs_exec_resource_changed(struct wined3d_cs *cs, const void * + const struct wined3d_cs_resource_changed *op = data; + struct wined3d_resource *resource = op->resource; + +- wined3d_resource_changed(resource, op->swap_buffer); ++ wined3d_resource_changed(resource, op->swap_buffer, op->swap_heap_memory); + + return sizeof(*op); + } + + void wined3d_cs_emit_resource_changed(struct wined3d_cs *cs, struct wined3d_resource *resource, +- struct wined3d_gl_bo *swap_buffer) ++ struct wined3d_gl_bo *swap_buffer, void *swap_heap_memory) + { + struct wined3d_cs_resource_changed *op; + +@@ -1831,6 +1832,7 @@ void wined3d_cs_emit_resource_changed(struct wined3d_cs *cs, struct wined3d_reso + op->opcode = WINED3D_CS_OP_RESOURCE_CHANGED; + op->resource = resource; + op->swap_buffer = swap_buffer; ++ op->swap_heap_memory = swap_heap_memory; + + cs->ops->submit(cs, sizeof(*op)); + } +diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c +index 8d9757c..ef0b213 100644 +--- a/dlls/wined3d/resource.c ++++ b/dlls/wined3d/resource.c +@@ -119,6 +119,7 @@ HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device * + ERR("Failed to allocate system memory.\n"); + return E_OUTOFMEMORY; + } ++ resource->heap_memory = resource->map_heap_memory; + } + else + { +@@ -172,6 +173,7 @@ void resource_cleanup(struct wined3d_resource *resource) + wined3d_resource_free_bo(resource); + + wined3d_resource_free_sysmem(resource); ++ resource->map_heap_memory = NULL; + + device_resource_released(resource->device, resource); + } +@@ -246,7 +248,7 @@ BOOL wined3d_resource_allocate_sysmem(struct wined3d_resource *resource) + p = (void **)(((ULONG_PTR)mem + align) & ~(RESOURCE_ALIGNMENT - 1)) - 1; + *p = mem; + +- resource->heap_memory = ++p; ++ resource->map_heap_memory = ++p; + + return TRUE; + } +@@ -528,7 +530,7 @@ BYTE *wined3d_resource_get_map_ptr(const struct wined3d_resource *resource, + return ptr; + + case WINED3D_LOCATION_SYSMEM: +- return resource->heap_memory; ++ return resource->map_heap_memory; + + case WINED3D_LOCATION_DIB: + return resource->bitmap_data; +@@ -590,6 +592,7 @@ BOOL wined3d_resource_prepare_system_memory(struct wined3d_resource *resource) + ERR("Failed to allocate system memory.\n"); + return FALSE; + } ++ resource->heap_memory = resource->map_heap_memory; + return TRUE; + } + +@@ -705,6 +708,10 @@ void *wined3d_resource_map_internal(struct wined3d_resource *resource, DWORD fla + GL_STREAM_DRAW_ARB, GL_PIXEL_UNPACK_BUFFER_ARB, context); + break; + ++ case WINED3D_LOCATION_SYSMEM: ++ wined3d_resource_allocate_sysmem(resource); ++ break; ++ + default: + if (resource->access_fence) + ERR("Location %s does not support DISCARD maps.\n", +@@ -773,7 +780,21 @@ HRESULT wined3d_resource_map(struct wined3d_resource *resource, + if (flags & WINED3D_MAP_NOOVERWRITE) + FIXME("WINED3D_MAP_NOOVERWRITE are not implemented yet.\n"); + +- if (!(flags & WINED3D_MAP_DISCARD) || resource->map_binding != WINED3D_LOCATION_BUFFER) ++ if (flags & WINED3D_MAP_DISCARD) ++ { ++ switch (resource->map_binding) ++ { ++ case WINED3D_LOCATION_BUFFER: ++ case WINED3D_LOCATION_SYSMEM: ++ break; ++ ++ default: ++ FIXME("Implement discard maps with %s map binding.\n", ++ wined3d_debug_location(resource->map_binding)); ++ wined3d_resource_sync(resource); ++ } ++ } ++ else + wined3d_resource_sync(resource); + + base_memory = wined3d_cs_emit_resource_map(device->cs, resource, flags); +@@ -860,7 +881,10 @@ HRESULT wined3d_resource_unmap(struct wined3d_resource *resource) + wined3d_cs_emit_resource_unmap(device->cs, resource); + + if (resource->unmap_dirtify) +- wined3d_cs_emit_resource_changed(device->cs, resource, resource->map_buffer); ++ { ++ wined3d_cs_emit_resource_changed(device->cs, resource, ++ resource->map_buffer, resource->map_heap_memory); ++ } + resource->unmap_dirtify = FALSE; + + resource->map_count--; +@@ -868,7 +892,8 @@ HRESULT wined3d_resource_unmap(struct wined3d_resource *resource) + return WINED3D_OK; + } + +-void wined3d_resource_changed(struct wined3d_resource *resource, struct wined3d_gl_bo *swap_buffer) ++void wined3d_resource_changed(struct wined3d_resource *resource, struct wined3d_gl_bo *swap_buffer, ++ void *swap_heap_memory) + { + struct wined3d_device *device = resource->device; + +@@ -879,6 +904,11 @@ void wined3d_resource_changed(struct wined3d_resource *resource, struct wined3d_ + context_release(context); + resource->buffer = swap_buffer; + } ++ if (swap_heap_memory && swap_heap_memory != resource->heap_memory) ++ { ++ wined3d_resource_free_sysmem(resource); ++ resource->heap_memory = swap_heap_memory; ++ } + + wined3d_resource_invalidate_location(resource, ~resource->map_binding); + } +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 7c532f0..73160ff 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -487,6 +487,7 @@ static void surface_evict_sysmem(struct wined3d_surface *surface) + return; + + wined3d_resource_free_sysmem(&surface->resource); ++ surface->resource.map_heap_memory = NULL; + wined3d_resource_invalidate_location(&surface->resource, WINED3D_LOCATION_SYSMEM); + } + +@@ -1996,6 +1997,7 @@ HRESULT wined3d_surface_update_desc(struct wined3d_surface *surface, + + surface->resource.locations = 0; + wined3d_resource_free_sysmem(&surface->resource); ++ surface->resource.map_heap_memory = NULL; + + width = texture_resource->width; + height = texture_resource->height; +@@ -5334,6 +5336,7 @@ static HRESULT surface_init(struct wined3d_surface *surface, struct wined3d_text + if (surface->resource.map_binding == WINED3D_LOCATION_DIB) + { + wined3d_resource_free_sysmem(&surface->resource); ++ surface->resource.map_heap_memory = NULL; + wined3d_resource_validate_location(&surface->resource, WINED3D_LOCATION_DIB); + wined3d_resource_invalidate_location(&surface->resource, WINED3D_LOCATION_SYSMEM); + } +diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c +index 467169f..34b72d1 100644 +--- a/dlls/wined3d/volume.c ++++ b/dlls/wined3d/volume.c +@@ -120,6 +120,7 @@ static void wined3d_volume_download_data(struct wined3d_volume *volume, + static void wined3d_volume_evict_sysmem(struct wined3d_volume *volume) + { + wined3d_resource_free_sysmem(&volume->resource); ++ volume->resource.map_heap_memory = NULL; + wined3d_resource_invalidate_location(&volume->resource, WINED3D_LOCATION_SYSMEM); + } + +@@ -502,6 +503,7 @@ static HRESULT volume_init(struct wined3d_volume *volume, struct wined3d_texture + { + wined3d_resource_free_sysmem(&volume->resource); + volume->resource.map_binding = WINED3D_LOCATION_BUFFER; ++ volume->resource.map_heap_memory = NULL; + } + + volume->container = container; +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 15d63e2..270162f 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2126,7 +2126,7 @@ struct wined3d_resource + UINT depth; + UINT size; + DWORD priority; +- void *heap_memory, *user_memory, *bitmap_data; ++ void *heap_memory, *map_heap_memory, *user_memory, *bitmap_data; + struct wined3d_gl_bo *buffer, *map_buffer; + UINT custom_row_pitch, custom_slice_pitch; + struct list resource_list_entry; +@@ -2160,7 +2160,7 @@ void resource_unload(struct wined3d_resource *resource) DECLSPEC_HIDDEN; + 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, +- struct wined3d_gl_bo *swap_buffer) DECLSPEC_HIDDEN; ++ struct wined3d_gl_bo *swap_buffer, void *swap_heap_memory) DECLSPEC_HIDDEN; + BOOL wined3d_resource_check_block_align(const struct wined3d_resource *resource, + const struct wined3d_box *box) DECLSPEC_HIDDEN; + void wined3d_resource_free_bo(struct wined3d_resource *resource) DECLSPEC_HIDDEN; +@@ -2678,7 +2678,7 @@ void wined3d_cs_emit_blt(struct wined3d_cs *cs, struct wined3d_surface *dst_surf + void wined3d_cs_emit_clear_rtv(struct wined3d_cs *cs, struct wined3d_rendertarget_view *view, + const RECT *rect, const struct wined3d_color *color) DECLSPEC_HIDDEN; + void wined3d_cs_emit_resource_changed(struct wined3d_cs *cs, struct wined3d_resource *resource, +- struct wined3d_gl_bo *swap_buffer) DECLSPEC_HIDDEN; ++ struct wined3d_gl_bo *swap_buffer, void *swap_heap_memory) DECLSPEC_HIDDEN; + void *wined3d_cs_emit_resource_map(struct wined3d_cs *cs, struct wined3d_resource *resource, + DWORD flags) DECLSPEC_HIDDEN; + void wined3d_cs_emit_resource_unmap(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0118-wined3d-Unset-some-objects-in-state_init_default.patch b/patches/wined3d-CSMT_Main/0118-wined3d-Unset-some-objects-in-state_init_default.patch new file mode 100644 index 00000000..7fe5a47e --- /dev/null +++ b/patches/wined3d-CSMT_Main/0118-wined3d-Unset-some-objects-in-state_init_default.patch @@ -0,0 +1,34 @@ +From 09ff7fca62f88791ece6e95f287579687418ba24 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Tue, 1 Oct 2013 21:30:07 +0200 +Subject: wined3d: Unset some objects in state_init_default. + +FIXME: Many more are needed. +FIXME2: Is this still needed? +--- + dlls/wined3d/stateblock.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c +index 606134c..690bcc7 100644 +--- a/dlls/wined3d/stateblock.c ++++ b/dlls/wined3d/stateblock.c +@@ -1339,7 +1339,15 @@ static void state_init_default(struct wined3d_state *state, const struct wined3d + 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; ++ state->textures[i] = NULL; + } ++ ++ state->index_buffer = NULL; ++ for (i = 0; i < sizeof(state->streams) / sizeof(*state->streams); i++) ++ memset(&state->streams[i], 0, sizeof(state->streams[i])); ++ ++ state->shader[WINED3D_SHADER_TYPE_VERTEX] = NULL; ++ state->shader[WINED3D_SHADER_TYPE_PIXEL] = NULL; + } + + HRESULT state_init(struct wined3d_state *state, const struct wined3d_gl_info *gl_info, +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0119-wined3d-Don-t-request-the-frontbuffer-to-create-dumm.patch b/patches/wined3d-CSMT_Main/0119-wined3d-Don-t-request-the-frontbuffer-to-create-dumm.patch new file mode 100644 index 00000000..03fb9556 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0119-wined3d-Don-t-request-the-frontbuffer-to-create-dumm.patch @@ -0,0 +1,26 @@ +From 55240026af497ef2d4e3d8edc456e65b989bf59e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Wed, 2 Oct 2013 12:36:02 +0200 +Subject: wined3d: Don't request the frontbuffer to create dummy textures. + +--- + dlls/wined3d/device.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index 6f82385..f5cb7bd 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -905,8 +905,7 @@ HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device, + device->swapchains[0] = swapchain; + device_init_swapchain_state(device, swapchain); + +- context = context_acquire(device, +- surface_from_resource(wined3d_texture_get_sub_resource(swapchain->front_buffer, 0))); ++ context = context_acquire(device, NULL); + + create_dummy_textures(device, context); + +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0120-wined3d-Use-double-buffered-buffers-for-multithreade.patch b/patches/wined3d-CSMT_Main/0120-wined3d-Use-double-buffered-buffers-for-multithreade.patch new file mode 100644 index 00000000..52f96c03 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0120-wined3d-Use-double-buffered-buffers-for-multithreade.patch @@ -0,0 +1,26 @@ +From e54d3de255928108db07a5f3367213a24d8bf959 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 4 Jul 2013 23:44:11 +0200 +Subject: wined3d: Use double-buffered buffers for multithreaded CS + +--- + dlls/wined3d/buffer.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c +index 3ca1143..de0eaec 100644 +--- a/dlls/wined3d/buffer.c ++++ b/dlls/wined3d/buffer.c +@@ -1254,6 +1254,9 @@ static HRESULT buffer_init(struct wined3d_buffer *buffer, struct wined3d_device + } + buffer->maps_size = 1; + ++ if (wined3d_settings.cs_multithreaded) ++ buffer->flags |= WINED3D_BUFFER_DOUBLEBUFFER; ++ + return WINED3D_OK; + } + +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0121-wined3d-Don-t-synchronize-NOOVERWRITE-buffer-maps.patch b/patches/wined3d-CSMT_Main/0121-wined3d-Don-t-synchronize-NOOVERWRITE-buffer-maps.patch new file mode 100644 index 00000000..df49b45e --- /dev/null +++ b/patches/wined3d-CSMT_Main/0121-wined3d-Don-t-synchronize-NOOVERWRITE-buffer-maps.patch @@ -0,0 +1,58 @@ +From 4dab2b426c1d4eb918dda550a547b33858617395 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 4 Jul 2013 23:49:26 +0200 +Subject: wined3d: Don't synchronize NOOVERWRITE buffer maps + +TODO: Put the patch that makes PreLoad ignore the mapped state here. +--- + dlls/wined3d/buffer.c | 20 +++++++++++++------- + 1 file changed, 13 insertions(+), 7 deletions(-) + +diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c +index de0eaec..fd03fb5 100644 +--- a/dlls/wined3d/buffer.c ++++ b/dlls/wined3d/buffer.c +@@ -958,13 +958,6 @@ HRESULT CDECL wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UIN + + TRACE("buffer %p, offset %u, size %u, data %p, flags %#x\n", buffer, offset, size, data, flags); + +- if (wined3d_settings.cs_multithreaded) +- { +- FIXME("Waiting for cs.\n"); +- wined3d_cs_emit_glfinish(device->cs); +- device->cs->ops->finish(device->cs); +- } +- + flags = wined3d_resource_sanitize_map_flags(&buffer->resource, flags); + /* Filter redundant WINED3D_MAP_DISCARD maps. The 3DMark2001 multitexture + * fill rate test seems to depend on this. When we map a buffer with +@@ -995,6 +988,13 @@ HRESULT CDECL wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UIN + struct wined3d_context *context; + const struct wined3d_gl_info *gl_info; + ++ if (wined3d_settings.cs_multithreaded) ++ { ++ FIXME("waiting for cs\n"); ++ wined3d_cs_emit_glfinish(device->cs); ++ device->cs->ops->finish(device->cs); ++ } ++ + context = context_acquire(device, NULL); + gl_info = context->gl_info; + +@@ -1056,6 +1056,12 @@ HRESULT CDECL wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UIN + buffer->flags |= WINED3D_BUFFER_SYNC; + } + ++ if (!(flags & WINED3D_MAP_NOOVERWRITE) && wined3d_settings.cs_multithreaded) ++ { ++ FIXME("waiting for cs.\n"); ++ device->cs->ops->finish(device->cs); ++ } ++ + base = buffer->map_ptr ? buffer->map_ptr : buffer->resource.heap_memory; + *data = base + offset; + +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0122-wined3d-Separate-buffer-map-write-and-draw-read-memo.patch b/patches/wined3d-CSMT_Main/0122-wined3d-Separate-buffer-map-write-and-draw-read-memo.patch new file mode 100644 index 00000000..e69bdb4c --- /dev/null +++ b/patches/wined3d-CSMT_Main/0122-wined3d-Separate-buffer-map-write-and-draw-read-memo.patch @@ -0,0 +1,47 @@ +From eaad769483668455de518d4bea0013ddef6d5f6a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Sat, 6 Jul 2013 15:59:11 +0200 +Subject: wined3d: Separate buffer map write and draw read memory pointers + +TODO: Think about making this generic for all resources. +TODO 2: This is rather pointless on its own, merge this with the +patch that introduces this for all resources. +--- + dlls/wined3d/buffer.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c +index fd03fb5..2a814c6 100644 +--- a/dlls/wined3d/buffer.c ++++ b/dlls/wined3d/buffer.c +@@ -191,7 +191,10 @@ static void buffer_create_buffer_object(struct wined3d_buffer *This, struct wine + if (This->flags & WINED3D_BUFFER_DOUBLEBUFFER) + buffer_invalidate_bo_range(This, 0, 0); + else ++ { + wined3d_resource_free_sysmem(&This->resource); ++ This->resource.map_heap_memory = NULL; ++ } + + return; + +@@ -1044,7 +1047,6 @@ HRESULT CDECL wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UIN + buffer_get_sysmem(buffer, context); + } + TRACE("New pointer is %p.\n", buffer->resource.heap_memory); +- buffer->map_ptr = NULL; + } + context_release(context); + } +@@ -1062,7 +1064,7 @@ HRESULT CDECL wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UIN + device->cs->ops->finish(device->cs); + } + +- base = buffer->map_ptr ? buffer->map_ptr : buffer->resource.heap_memory; ++ base = buffer->map_ptr ? buffer->map_ptr : buffer->resource.map_heap_memory; + *data = base + offset; + + TRACE("Returning memory at %p (base %p, offset %u).\n", *data, base, offset); +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0123-wined3d-Accelerate-DISCARD-buffer-maps.patch b/patches/wined3d-CSMT_Main/0123-wined3d-Accelerate-DISCARD-buffer-maps.patch new file mode 100644 index 00000000..bf768f2f --- /dev/null +++ b/patches/wined3d-CSMT_Main/0123-wined3d-Accelerate-DISCARD-buffer-maps.patch @@ -0,0 +1,139 @@ +From 46ed74a72057957b7046b45b4cdfb4b34ad4016e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Sat, 6 Jul 2013 16:14:16 +0200 +Subject: wined3d: Accelerate DISCARD buffer maps + +TODO: Make this generic for all resources. +TODO2: Merge this with the patch that controlls BUFFER_DISCARD in the CS thread +TODO3: Clean up the map_mem allocation mess. +--- + dlls/wined3d/buffer.c | 15 ++++++++++++--- + dlls/wined3d/cs.c | 39 ++++++++++++++++++++++++++++++++++++++- + dlls/wined3d/wined3d_private.h | 2 ++ + 3 files changed, 52 insertions(+), 4 deletions(-) + +diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c +index 2a814c6..5c6d36e 100644 +--- a/dlls/wined3d/buffer.c ++++ b/dlls/wined3d/buffer.c +@@ -1058,10 +1058,19 @@ HRESULT CDECL wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UIN + buffer->flags |= WINED3D_BUFFER_SYNC; + } + +- if (!(flags & WINED3D_MAP_NOOVERWRITE) && wined3d_settings.cs_multithreaded) ++ if (wined3d_settings.cs_multithreaded && count == 1) + { +- FIXME("waiting for cs.\n"); +- device->cs->ops->finish(device->cs); ++ BOOL swvp = device->create_parms.flags & WINED3DCREATE_SOFTWARE_VERTEXPROCESSING; ++ if (flags & WINED3D_MAP_DISCARD && !swvp) ++ { ++ wined3d_resource_allocate_sysmem(&buffer->resource); ++ wined3d_cs_emit_buffer_swap_mem(device->cs, buffer, buffer->resource.map_heap_memory); ++ } ++ else if(!(flags & WINED3D_MAP_NOOVERWRITE)) ++ { ++ FIXME("waiting for cs.\n"); ++ device->cs->ops->finish(device->cs); ++ } + } + + base = buffer->map_ptr ? buffer->map_ptr : buffer->resource.map_heap_memory; +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 9307246..341b51c 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -68,6 +68,7 @@ enum wined3d_cs_op + WINED3D_CS_OP_RESOURCE_CHANGED, + WINED3D_CS_OP_RESOURCE_MAP, + WINED3D_CS_OP_RESOURCE_UNMAP, ++ WINED3D_CS_OP_BUFFER_SWAP_MEM, + WINED3D_CS_OP_QUERY_ISSUE, + WINED3D_CS_OP_QUERY_DESTROY, + WINED3D_CS_OP_UPDATE_SURFACE, +@@ -374,6 +375,13 @@ struct wined3d_cs_resource_changed + void *swap_heap_memory; + }; + ++struct wined3d_cs_buffer_swap_mem ++{ ++ enum wined3d_cs_op opcode; ++ struct wined3d_buffer *buffer; ++ BYTE *mem; ++}; ++ + struct wined3d_cs_skip + { + enum wined3d_cs_op opcode; +@@ -2123,6 +2131,34 @@ void wined3d_cs_emit_evict_resource(struct wined3d_cs *cs, struct wined3d_resour + cs->ops->submit(cs, sizeof(*op)); + } + ++static UINT wined3d_cs_exec_buffer_swap_mem(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_buffer_swap_mem *op = data; ++ struct wined3d_buffer *buffer = op->buffer; ++ ++ wined3d_resource_free_sysmem(&buffer->resource); ++ buffer->resource.heap_memory = op->mem; ++ ++ if (!buffer->buffer_object && buffer->resource.bind_count) ++ { ++ device_invalidate_state(cs->device, STATE_STREAMSRC); ++ device_invalidate_state(cs->device, STATE_INDEXBUFFER); ++ } ++ return sizeof(*op); ++} ++ ++void wined3d_cs_emit_buffer_swap_mem(struct wined3d_cs *cs, struct wined3d_buffer *buffer, BYTE *mem) ++{ ++ struct wined3d_cs_buffer_swap_mem *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_BUFFER_SWAP_MEM; ++ op->buffer = buffer; ++ op->mem = mem; ++ ++ cs->ops->submit(cs, sizeof(*op)); ++} ++ + static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = + { + /* WINED3D_CS_OP_NOP */ wined3d_cs_exec_nop, +@@ -2143,11 +2179,11 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* 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_SHADER_RESOURCE_VIEW */ wined3d_cs_exec_set_shader_resource_view, + /* 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, +@@ -2169,6 +2205,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* 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_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, +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 270162f..7d12df9 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2694,6 +2694,8 @@ void wined3d_cs_emit_surface_preload(struct wined3d_cs *cs, struct wined3d_surfa + void wined3d_cs_emit_update_texture(struct wined3d_cs *cs, struct wined3d_texture *src, + struct wined3d_texture *dst) DECLSPEC_HIDDEN; + void wined3d_cs_emit_evict_resource(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_buffer_swap_mem(struct wined3d_cs *cs, struct wined3d_buffer *buffer, ++ BYTE *mem) DECLSPEC_HIDDEN; + + /* 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 +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0124-wined3d-Accelerate-READONLY-buffer-maps.patch b/patches/wined3d-CSMT_Main/0124-wined3d-Accelerate-READONLY-buffer-maps.patch new file mode 100644 index 00000000..399c504e --- /dev/null +++ b/patches/wined3d-CSMT_Main/0124-wined3d-Accelerate-READONLY-buffer-maps.patch @@ -0,0 +1,29 @@ +From 14090e86e52e7fcc475ae83c3a25039a313a6d32 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Sat, 6 Jul 2013 16:44:35 +0200 +Subject: wined3d: Accelerate READONLY buffer maps + +FIXME: ProcessVertices can write to buffers +--- + dlls/wined3d/buffer.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c +index 5c6d36e..f4c0d07 100644 +--- a/dlls/wined3d/buffer.c ++++ b/dlls/wined3d/buffer.c +@@ -1066,9 +1066,9 @@ HRESULT CDECL wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UIN + wined3d_resource_allocate_sysmem(&buffer->resource); + wined3d_cs_emit_buffer_swap_mem(device->cs, buffer, buffer->resource.map_heap_memory); + } +- else if(!(flags & WINED3D_MAP_NOOVERWRITE)) ++ else if(!(flags & (WINED3D_MAP_NOOVERWRITE | WINED3D_MAP_READONLY))) + { +- FIXME("waiting for cs.\n"); ++ FIXME("waiting for cs, flags 0x%04x.\n", flags); + device->cs->ops->finish(device->cs); + } + } +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0125-wined3d-Access-the-buffer-dirty-areas-through-the-CS.patch b/patches/wined3d-CSMT_Main/0125-wined3d-Access-the-buffer-dirty-areas-through-the-CS.patch new file mode 100644 index 00000000..dbcbf70b --- /dev/null +++ b/patches/wined3d-CSMT_Main/0125-wined3d-Access-the-buffer-dirty-areas-through-the-CS.patch @@ -0,0 +1,140 @@ +From b2574fe8833075c9f1c7fab68bf04dc73b749a42 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Sat, 6 Jul 2013 17:05:12 +0200 +Subject: wined3d: Access the buffer dirty areas through the CS + +This avoids the following issues: + +1) The worker thread uploading a dirtified area before the application +unlocks the buffer and marking it clean + +2) The worker thread uploading data from the old memory and marking the +area clean although the data was written to a new block of memory. + +However, this adds more synchronization than necessary. The first +problem could be solved by moving dirtification to unmap, e.g. via a +flag in each dirty area. The second problem can be fixed by not +dirtifying in map if map_mem != resource.allocatedMemory and dirtifying +the entire buffer in buffer_swap_memory (DISCARD dirtifies the entire +buffer anyway, and this could be the reason why). + +If one of those ideas is used, access to the dirty area array needs to +be protected by locks. +--- + dlls/wined3d/buffer.c | 6 +++--- + dlls/wined3d/cs.c | 31 +++++++++++++++++++++++++++++++ + dlls/wined3d/wined3d_private.h | 3 +++ + 3 files changed, 37 insertions(+), 3 deletions(-) + +diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c +index f4c0d07..551cc7a 100644 +--- a/dlls/wined3d/buffer.c ++++ b/dlls/wined3d/buffer.c +@@ -41,7 +41,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); + #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) ++void buffer_invalidate_bo_range(struct wined3d_buffer *buffer, UINT offset, UINT size) + { + if (!offset && !size) + goto invalidate_all; +@@ -979,9 +979,9 @@ HRESULT CDECL wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UIN + * being uploaded in that case. Two such applications are Port Royale + * and Darkstar One. */ + if (flags & WINED3D_MAP_DISCARD) +- buffer_invalidate_bo_range(buffer, 0, 0); ++ wined3d_cs_emit_buffer_invalidate_bo_range(device->cs, buffer, 0, 0); + else if (!(flags & WINED3D_MAP_READONLY)) +- buffer_invalidate_bo_range(buffer, offset, size); ++ wined3d_cs_emit_buffer_invalidate_bo_range(device->cs, buffer, offset, size); + + if (!(buffer->flags & WINED3D_BUFFER_DOUBLEBUFFER)) + { +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 341b51c..179f2e6 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -69,6 +69,7 @@ enum wined3d_cs_op + WINED3D_CS_OP_RESOURCE_MAP, + WINED3D_CS_OP_RESOURCE_UNMAP, + WINED3D_CS_OP_BUFFER_SWAP_MEM, ++ WINED3D_CS_OP_BUFFER_INVALIDATE_RANGE, + WINED3D_CS_OP_QUERY_ISSUE, + WINED3D_CS_OP_QUERY_DESTROY, + WINED3D_CS_OP_UPDATE_SURFACE, +@@ -382,6 +383,13 @@ struct wined3d_cs_buffer_swap_mem + BYTE *mem; + }; + ++struct wined3d_cs_buffer_invalidate_bo_range ++{ ++ enum wined3d_cs_op opcode; ++ struct wined3d_buffer *buffer; ++ UINT offset, size; ++}; ++ + struct wined3d_cs_skip + { + enum wined3d_cs_op opcode; +@@ -2159,6 +2167,28 @@ void wined3d_cs_emit_buffer_swap_mem(struct wined3d_cs *cs, struct wined3d_buffe + cs->ops->submit(cs, sizeof(*op)); + } + ++static UINT wined3d_cs_exec_buffer_invalidate_bo_range(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_buffer_invalidate_bo_range *op = data; ++ ++ buffer_invalidate_bo_range(op->buffer, op->offset, op->size); ++ return sizeof(*op); ++} ++ ++void wined3d_cs_emit_buffer_invalidate_bo_range(struct wined3d_cs *cs, ++ struct wined3d_buffer *buffer, UINT offset, UINT size) ++{ ++ struct wined3d_cs_buffer_invalidate_bo_range *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_BUFFER_INVALIDATE_RANGE; ++ op->buffer = buffer; ++ op->offset = offset; ++ op->size = size; ++ ++ cs->ops->submit(cs, sizeof(*op)); ++} ++ + static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = + { + /* WINED3D_CS_OP_NOP */ wined3d_cs_exec_nop, +@@ -2206,6 +2236,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* 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_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, +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 7d12df9..c683880 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2696,6 +2696,8 @@ void wined3d_cs_emit_update_texture(struct wined3d_cs *cs, struct wined3d_textur + void wined3d_cs_emit_evict_resource(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN; + void wined3d_cs_emit_buffer_swap_mem(struct wined3d_cs *cs, struct wined3d_buffer *buffer, + BYTE *mem) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_buffer_invalidate_bo_range(struct wined3d_cs *cs, ++ struct wined3d_buffer *buffer, UINT offset, UINT size) DECLSPEC_HIDDEN; + + /* 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 +@@ -2781,6 +2783,7 @@ void buffer_get_memory(struct wined3d_buffer *buffer, struct wined3d_context *co + 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; ++void buffer_invalidate_bo_range(struct wined3d_buffer *This, UINT offset, UINT size) DECLSPEC_HIDDEN; + + struct wined3d_rendertarget_view + { +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0126-wined3d-Ignore-buffer-resource.map_count-in-the-CS.patch b/patches/wined3d-CSMT_Main/0126-wined3d-Ignore-buffer-resource.map_count-in-the-CS.patch new file mode 100644 index 00000000..5e223b19 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0126-wined3d-Ignore-buffer-resource.map_count-in-the-CS.patch @@ -0,0 +1,58 @@ +From e7637b3b410855296289ec8ebe199b80b5a7a2b0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Sat, 6 Jul 2013 22:52:06 +0200 +Subject: wined3d: Ignore buffer->resource.map_count in the CS + +This fixes sporadic test failures caused by preload refusing to load +data into the GL buffer. + +It's fine to preload or create a VBO if a DISCARD or NOOVERWRITE map is +happening at the same time. A non-dynamic map will finish the CS before +incrementing map_count. +--- + dlls/wined3d/buffer.c | 15 ++++++++------- + 1 file changed, 8 insertions(+), 7 deletions(-) + +diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c +index 551cc7a..3ac45c6 100644 +--- a/dlls/wined3d/buffer.c ++++ b/dlls/wined3d/buffer.c +@@ -457,7 +457,8 @@ void buffer_get_memory(struct wined3d_buffer *buffer, struct wined3d_context *co + data->buffer_object = buffer->buffer_object; + if (!buffer->buffer_object) + { +- if ((buffer->flags & WINED3D_BUFFER_CREATEBO) && !buffer->resource.map_count) ++ if ((!buffer->resource.map_count || buffer->flags & WINED3D_BUFFER_DOUBLEBUFFER) ++ && buffer->flags & WINED3D_BUFFER_CREATEBO) + { + buffer_create_buffer_object(buffer, context); + buffer->flags &= ~WINED3D_BUFFER_CREATEBO; +@@ -737,12 +738,6 @@ void buffer_internal_preload(struct wined3d_buffer *buffer, struct wined3d_conte + + TRACE("buffer %p.\n", buffer); + +- if (buffer->resource.map_count) +- { +- WARN("Buffer is mapped, skipping preload.\n"); +- return; +- } +- + buffer_mark_used(buffer); + + if (!buffer->buffer_object) +@@ -934,6 +929,12 @@ void CDECL wined3d_buffer_preload(struct wined3d_buffer *buffer) + struct wined3d_context *context; + struct wined3d_device *device = buffer->resource.device; + ++ if (buffer->resource.map_count) ++ { ++ WARN("Buffer is mapped, skipping preload.\n"); ++ return; ++ } ++ + if (wined3d_settings.cs_multithreaded) + { + FIXME("Waiting for cs.\n"); +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0127-wined3d-Send-buffer-preloads-through-the-CS.patch b/patches/wined3d-CSMT_Main/0127-wined3d-Send-buffer-preloads-through-the-CS.patch new file mode 100644 index 00000000..0af85030 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0127-wined3d-Send-buffer-preloads-through-the-CS.patch @@ -0,0 +1,122 @@ +From f0608f8a5916eea7e342db36ffe49427e40a4b49 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Sun, 7 Jul 2013 12:02:59 +0200 +Subject: wined3d: Send buffer preloads through the CS + +Think about making this a fast command. Might help if the driver +supports async data transfer, but synchronization side effects, esp. wrt +the dirty area list, have to be considered. +--- + dlls/wined3d/buffer.c | 12 +----------- + dlls/wined3d/cs.c | 31 +++++++++++++++++++++++++++++++ + dlls/wined3d/wined3d_private.h | 1 + + 3 files changed, 33 insertions(+), 11 deletions(-) + +diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c +index 3ac45c6..a09ca90 100644 +--- a/dlls/wined3d/buffer.c ++++ b/dlls/wined3d/buffer.c +@@ -926,7 +926,6 @@ void buffer_internal_preload(struct wined3d_buffer *buffer, struct wined3d_conte + + void CDECL wined3d_buffer_preload(struct wined3d_buffer *buffer) + { +- struct wined3d_context *context; + struct wined3d_device *device = buffer->resource.device; + + if (buffer->resource.map_count) +@@ -935,16 +934,7 @@ void CDECL wined3d_buffer_preload(struct wined3d_buffer *buffer) + return; + } + +- if (wined3d_settings.cs_multithreaded) +- { +- FIXME("Waiting for cs.\n"); +- wined3d_cs_emit_glfinish(device->cs); +- device->cs->ops->finish(device->cs); +- } +- +- context = context_acquire(buffer->resource.device, NULL); +- buffer_internal_preload(buffer, context, NULL); +- context_release(context); ++ wined3d_cs_emit_buffer_preload(device->cs, buffer); + } + + struct wined3d_resource * CDECL wined3d_buffer_get_resource(struct wined3d_buffer *buffer) +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 179f2e6..6b16d51 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -70,6 +70,7 @@ enum wined3d_cs_op + WINED3D_CS_OP_RESOURCE_UNMAP, + WINED3D_CS_OP_BUFFER_SWAP_MEM, + WINED3D_CS_OP_BUFFER_INVALIDATE_RANGE, ++ WINED3D_CS_OP_BUFFER_PRELOAD, + WINED3D_CS_OP_QUERY_ISSUE, + WINED3D_CS_OP_QUERY_DESTROY, + WINED3D_CS_OP_UPDATE_SURFACE, +@@ -442,6 +443,12 @@ struct wined3d_cs_evict_resource + struct wined3d_resource *resource; + }; + ++struct wined3d_cs_buffer_preload ++{ ++ enum wined3d_cs_op opcode; ++ struct wined3d_buffer *buffer; ++}; ++ + static void wined3d_cs_mt_submit(struct wined3d_cs *cs, size_t size) + { + LONG new_val = (cs->queue.head + size) & (WINED3D_CS_QUEUE_SIZE - 1); +@@ -2189,6 +2196,29 @@ void wined3d_cs_emit_buffer_invalidate_bo_range(struct wined3d_cs *cs, + cs->ops->submit(cs, sizeof(*op)); + } + ++static UINT wined3d_cs_exec_buffer_preload(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_buffer_preload *op = data; ++ struct wined3d_context *context; ++ ++ context = context_acquire(cs->device, NULL); ++ buffer_internal_preload(op->buffer, context, NULL); ++ context_release(context); ++ ++ return sizeof(*op); ++} ++ ++void wined3d_cs_emit_buffer_preload(struct wined3d_cs *cs, struct wined3d_buffer *buffer) ++{ ++ struct wined3d_cs_buffer_preload *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_BUFFER_PRELOAD; ++ op->buffer = buffer; ++ ++ cs->ops->submit(cs, sizeof(*op)); ++} ++ + static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = + { + /* WINED3D_CS_OP_NOP */ wined3d_cs_exec_nop, +@@ -2237,6 +2267,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* 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, +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index c683880..4070e1d 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2698,6 +2698,7 @@ void wined3d_cs_emit_buffer_swap_mem(struct wined3d_cs *cs, struct wined3d_buffe + BYTE *mem) DECLSPEC_HIDDEN; + void wined3d_cs_emit_buffer_invalidate_bo_range(struct wined3d_cs *cs, + struct wined3d_buffer *buffer, UINT offset, UINT size) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_buffer_preload(struct wined3d_cs *cs, struct wined3d_buffer *buffer) DECLSPEC_HIDDEN; + + /* 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 +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0128-wined3d-Use-glBufferSubData-instead-of-glMapBufferRa.patch b/patches/wined3d-CSMT_Main/0128-wined3d-Use-glBufferSubData-instead-of-glMapBufferRa.patch new file mode 100644 index 00000000..52ea5ae6 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0128-wined3d-Use-glBufferSubData-instead-of-glMapBufferRa.patch @@ -0,0 +1,91 @@ +From bca1f6b098077f30abc3d86ea3e7c3be17dc35f4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Wed, 24 Jul 2013 13:02:06 +0200 +Subject: wined3d: Use glBufferSubData instead of glMapBufferRange + +This is faster on Nvidia once we're stuck in double-buffer mode for some +reason (e.g. using threaded cs). For other cards, we want to be able to +do mapbuffer through the CS. +--- + dlls/wined3d/buffer.c | 50 ++++++-------------------------------------------- + 1 file changed, 6 insertions(+), 44 deletions(-) + +diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c +index a09ca90..675dbec 100644 +--- a/dlls/wined3d/buffer.c ++++ b/dlls/wined3d/buffer.c +@@ -657,43 +657,17 @@ drop_query: + /* The caller provides a GL context */ + static void buffer_direct_upload(struct wined3d_buffer *This, const struct wined3d_gl_info *gl_info, DWORD flags) + { +- 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(glBindBufferARB(This->buffer_type_hint, This->buffer_object)); + checkGLcall("glBindBufferARB"); +- 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(glMapBufferARB(This->buffer_type_hint, GL_WRITE_ONLY_ARB)); +- checkGLcall("glMapBufferARB"); +- } +- if (!map) ++ ++ if (flags & WINED3D_BUFFER_DISCARD) + { +- ERR("Failed to map opengl buffer\n"); +- return; ++ GL_EXTCALL(glBufferDataARB(This->buffer_type_hint, This->resource.size, NULL, GL_STREAM_DRAW_ARB)); ++ checkGLcall("glBufferDataARB"); + } + + while (This->modified_areas) +@@ -702,21 +676,9 @@ static void buffer_direct_upload(struct wined3d_buffer *This, const struct wined + start = This->maps[This->modified_areas].offset; + len = This->maps[This->modified_areas].size; + +- 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_APPLESYNC) +- { +- GL_EXTCALL(glFlushMappedBufferRangeAPPLE(This->buffer_type_hint, start, len)); +- checkGLcall("glFlushMappedBufferRangeAPPLE"); +- } ++ GL_EXTCALL(glBufferSubDataARB(This->buffer_type_hint, start, len, (BYTE *)This->resource.heap_memory + start)); ++ checkGLcall("glBufferSubDataARB"); + } +- GL_EXTCALL(glUnmapBufferARB(This->buffer_type_hint)); +- checkGLcall("glUnmapBufferARB"); + } + + static void buffer_mark_used(struct wined3d_buffer *buffer) +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0129-wined3d-Separate-GL-buffer-discard-control-from-igno.patch b/patches/wined3d-CSMT_Main/0129-wined3d-Separate-GL-buffer-discard-control-from-igno.patch new file mode 100644 index 00000000..b4355ead --- /dev/null +++ b/patches/wined3d-CSMT_Main/0129-wined3d-Separate-GL-buffer-discard-control-from-igno.patch @@ -0,0 +1,135 @@ +From fd33771329457adaba5a2fb8006991e7ad756ec7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Tue, 30 Jul 2013 22:17:10 +0200 +Subject: wined3d: Separate GL buffer discard control from ignoring + MAP_DISCARD. + +Ignoring WINED3D_MAP_DISCARD is controlled purely in the main thread, +whereas the other one is controlled in the worker thread. Store them in +separate fields for synchronization purposes. + +There are some problems left: +* buffer->flags is still accessed by both threads without sync. +* CSMT=off has a separate codepath that is untested. +--- + dlls/wined3d/buffer.c | 25 +++++++++++++++++++------ + dlls/wined3d/cs.c | 9 +++++++-- + dlls/wined3d/wined3d_private.h | 2 ++ + 3 files changed, 28 insertions(+), 8 deletions(-) + +diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c +index 675dbec..8b09aee 100644 +--- a/dlls/wined3d/buffer.c ++++ b/dlls/wined3d/buffer.c +@@ -32,7 +32,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); + #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. */ +-#define WINED3D_BUFFER_DISCARD 0x08 /* A DISCARD lock has occurred since the last preload. */ ++#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. */ + +@@ -921,7 +921,7 @@ HRESULT CDECL wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UIN + * 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 (buffer->flags & WINED3D_BUFFER_DISCARD) ++ if (buffer->ignore_discard) + flags &= ~WINED3D_MAP_DISCARD; + count = ++buffer->resource.map_count; + +@@ -1004,10 +1004,15 @@ HRESULT CDECL wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UIN + context_release(context); + } + } +- +- if (flags & WINED3D_MAP_DISCARD) +- buffer->flags |= WINED3D_BUFFER_DISCARD; +- else if (!(flags & WINED3D_MAP_NOOVERWRITE)) ++ else if(!wined3d_settings.cs_multithreaded) ++ { ++ if (flags & WINED3D_MAP_DISCARD) ++ { ++ buffer->flags |= WINED3D_BUFFER_DISCARD; ++ buffer->ignore_discard = TRUE; ++ } ++ } ++ if (!(flags & (WINED3D_MAP_NOOVERWRITE | WINED3D_MAP_DISCARD))) + buffer->flags |= WINED3D_BUFFER_SYNC; + } + +@@ -1016,6 +1021,7 @@ HRESULT CDECL wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UIN + BOOL swvp = device->create_parms.flags & WINED3DCREATE_SOFTWARE_VERTEXPROCESSING; + if (flags & WINED3D_MAP_DISCARD && !swvp) + { ++ buffer->ignore_discard = TRUE; + wined3d_resource_allocate_sysmem(&buffer->resource); + wined3d_cs_emit_buffer_swap_mem(device->cs, buffer, buffer->resource.map_heap_memory); + } +@@ -1332,3 +1338,10 @@ HRESULT CDECL wined3d_buffer_create_ib(struct wined3d_device *device, UINT size, + + return WINED3D_OK; + } ++ ++void buffer_swap_mem(struct wined3d_buffer *buffer, BYTE *mem) ++{ ++ wined3d_resource_free_sysmem(&buffer->resource); ++ buffer->resource.heap_memory = mem; ++ buffer->flags |= WINED3D_BUFFER_DISCARD; ++} +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 6b16d51..4b9af57 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -722,11 +722,17 @@ void wined3d_cs_emit_draw(struct wined3d_cs *cs, UINT start_idx, UINT index_coun + op->indexed = indexed; + + if (indexed) ++ { + wined3d_resource_inc_fence(&state->index_buffer->resource); ++ state->index_buffer->ignore_discard = FALSE; ++ } + for (i = 0; i < sizeof(state->streams) / sizeof(*state->streams); i++) + { + if (state->streams[i].buffer) ++ { + wined3d_resource_inc_fence(&state->streams[i].buffer->resource); ++ state->streams[i].buffer->ignore_discard = FALSE; ++ } + } + for (i = 0; i < sizeof(state->textures) / sizeof(*state->textures); i++) + { +@@ -2151,8 +2157,7 @@ static UINT wined3d_cs_exec_buffer_swap_mem(struct wined3d_cs *cs, const void *d + const struct wined3d_cs_buffer_swap_mem *op = data; + struct wined3d_buffer *buffer = op->buffer; + +- wined3d_resource_free_sysmem(&buffer->resource); +- buffer->resource.heap_memory = op->mem; ++ buffer_swap_mem(buffer, op->mem); + + if (!buffer->buffer_object && buffer->resource.bind_count) + { +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 4070e1d..0f88961 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2760,6 +2760,7 @@ struct wined3d_buffer + GLenum buffer_object_usage; + GLenum buffer_type_hint; + DWORD flags; ++ BOOL ignore_discard; + void *map_ptr; + + struct wined3d_map_range *maps; +@@ -2785,6 +2786,7 @@ BYTE *buffer_get_sysmem(struct wined3d_buffer *This, struct wined3d_context *con + void buffer_internal_preload(struct wined3d_buffer *buffer, struct wined3d_context *context, + const struct wined3d_state *state) DECLSPEC_HIDDEN; + 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; + + struct wined3d_rendertarget_view + { +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0130-wined3d-Create-buffers-before-mapping-them.patch b/patches/wined3d-CSMT_Main/0130-wined3d-Create-buffers-before-mapping-them.patch new file mode 100644 index 00000000..5e6f78db --- /dev/null +++ b/patches/wined3d-CSMT_Main/0130-wined3d-Create-buffers-before-mapping-them.patch @@ -0,0 +1,66 @@ +From f11244b08c7979837fb685d1406f17d9630c6c98 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 29 Aug 2013 17:35:53 +0200 +Subject: wined3d: Create buffers before mapping them. + +--- + dlls/wined3d/buffer.c | 26 +++++++++++++++++++++++++- + 1 file changed, 25 insertions(+), 1 deletion(-) + +diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c +index 8b09aee..81c607d 100644 +--- a/dlls/wined3d/buffer.c ++++ b/dlls/wined3d/buffer.c +@@ -185,6 +185,8 @@ static void buffer_create_buffer_object(struct wined3d_buffer *This, struct wine + ERR("glBufferDataARB failed with error %s (%#x)\n", debug_glerror(error), error); + goto fail; + } ++ if (wined3d_settings.strict_draw_ordering || wined3d_settings.cs_multithreaded) ++ gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ + + This->buffer_object_usage = gl_usage; + +@@ -911,9 +913,32 @@ HRESULT CDECL wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UIN + LONG count; + BYTE *base; + struct wined3d_device *device = buffer->resource.device; ++ struct wined3d_context *context; + + TRACE("buffer %p, offset %u, size %u, data %p, flags %#x\n", buffer, offset, size, data, flags); + ++ /* FIXME: There is a race condition with the same code in ++ * buffer_internal_preload and buffer_get_memory. ++ * ++ * This deals with a race condition concering buffer creation and buffer maps. ++ * If a VBO is created by the worker thread while the buffer is mapped, outdated ++ * data may be uploaded, and the BO range is not properly invaliated. Keep in ++ * mind that a broken application might draw from a buffer before mapping it. ++ * ++ * Don't try to solve this by going back to always invalidating changed areas. ++ * This won't work if we ever want to support glMapBufferRange mapping with ++ * GL_ARB_buffer_storage in the CS. ++ * ++ * Also keep in mind that UnLoad can destroy the VBO, so simply creating it ++ * on buffer creation won't work either. */ ++ if (buffer->flags & WINED3D_BUFFER_CREATEBO) ++ { ++ context = context_acquire(device, NULL); ++ buffer_create_buffer_object(buffer, context); ++ context_release(context); ++ buffer->flags &= ~WINED3D_BUFFER_CREATEBO; ++ } ++ + flags = wined3d_resource_sanitize_map_flags(&buffer->resource, flags); + /* Filter redundant WINED3D_MAP_DISCARD maps. The 3DMark2001 multitexture + * fill rate test seems to depend on this. When we map a buffer with +@@ -941,7 +966,6 @@ HRESULT CDECL wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UIN + if (count == 1) + { + struct wined3d_device *device = buffer->resource.device; +- struct wined3d_context *context; + const struct wined3d_gl_info *gl_info; + + if (wined3d_settings.cs_multithreaded) +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0131-wined3d-Destroy-views-through-the-CS.patch b/patches/wined3d-CSMT_Main/0131-wined3d-Destroy-views-through-the-CS.patch new file mode 100644 index 00000000..5571754f --- /dev/null +++ b/patches/wined3d-CSMT_Main/0131-wined3d-Destroy-views-through-the-CS.patch @@ -0,0 +1,173 @@ +From a31fb6ca1b9379028340024e2bd7e97e894b0532 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 21 Aug 2014 22:47:58 +0200 +Subject: wined3d: Destroy views through the CS. + +Move this ahead. This has caused sporadic test failures ever since blits were moved to the CS. + +Also contains an ugly hack for ffp_blit_depth_fill. +--- + dlls/wined3d/cs.c | 28 ++++++++++++++++++++++++++++ + dlls/wined3d/surface.c | 4 ++-- + dlls/wined3d/view.c | 29 ++++++++++++++++++++++++++++- + dlls/wined3d/wined3d_private.h | 4 ++++ + 4 files changed, 62 insertions(+), 3 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 4b9af57..8e48c55 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -78,6 +78,7 @@ enum wined3d_cs_op + WINED3D_CS_OP_SURFACE_PRELOAD, + WINED3D_CS_OP_UPDATE_TEXTURE, + WINED3D_CS_OP_EVICT_RESOURCE, ++ WINED3D_CS_OP_VIEW_DESTROY, + WINED3D_CS_OP_STOP, + }; + +@@ -449,6 +450,12 @@ struct wined3d_cs_buffer_preload + struct wined3d_buffer *buffer; + }; + ++struct wined3d_cs_view_destroy ++{ ++ enum wined3d_cs_op opcode; ++ struct wined3d_rendertarget_view *view; ++}; ++ + static void wined3d_cs_mt_submit(struct wined3d_cs *cs, size_t size) + { + LONG new_val = (cs->queue.head + size) & (WINED3D_CS_QUEUE_SIZE - 1); +@@ -2224,6 +2231,26 @@ void wined3d_cs_emit_buffer_preload(struct wined3d_cs *cs, struct wined3d_buffer + cs->ops->submit(cs, sizeof(*op)); + } + ++static UINT wined3d_cs_exec_view_destroy(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_view_destroy *op = data; ++ ++ wined3d_rendertarget_view_destroy(op->view); ++ ++ return sizeof(*op); ++} ++ ++void wined3d_cs_emit_view_destroy(struct wined3d_cs *cs, struct wined3d_rendertarget_view *view) ++{ ++ struct wined3d_cs_view_destroy *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_VIEW_DESTROY; ++ op->view = view; ++ ++ cs->ops->submit(cs, sizeof(*op)); ++} ++ + static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = + { + /* WINED3D_CS_OP_NOP */ wined3d_cs_exec_nop, +@@ -2280,6 +2307,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* 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, + }; + + static inline void *_wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size, BOOL prio) +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 73160ff..43f68c6 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -4140,7 +4140,7 @@ static HRESULT ffp_blit_color_fill(struct wined3d_device *device, struct wined3d + } + + device_clear_render_targets(device, 1, &fb, 1, dst_rect, &draw_rect, WINED3DCLEAR_TARGET, color, 0.0f, 0); +- wined3d_rendertarget_view_decref(view); ++ wined3d_rendertarget_view_decref_worker(view); + + return WINED3D_OK; + } +@@ -4160,7 +4160,7 @@ static HRESULT ffp_blit_depth_fill(struct wined3d_device *device, struct wined3d + } + + device_clear_render_targets(device, 0, &fb, 1, dst_rect, &draw_rect, WINED3DCLEAR_ZBUFFER, 0, depth, 0); +- wined3d_rendertarget_view_decref(fb.depth_stencil); ++ wined3d_rendertarget_view_decref_worker(fb.depth_stencil); + + return WINED3D_OK; + } +diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c +index 9cda64d..56eb7b3 100644 +--- a/dlls/wined3d/view.c ++++ b/dlls/wined3d/view.c +@@ -33,6 +33,11 @@ ULONG CDECL wined3d_rendertarget_view_incref(struct wined3d_rendertarget_view *v + return refcount; + } + ++void wined3d_rendertarget_view_destroy(struct wined3d_rendertarget_view *view) ++{ ++ HeapFree(GetProcessHeap(), 0, view); ++} ++ + ULONG CDECL wined3d_rendertarget_view_decref(struct wined3d_rendertarget_view *view) + { + ULONG refcount = InterlockedDecrement(&view->refcount); +@@ -41,11 +46,33 @@ ULONG CDECL wined3d_rendertarget_view_decref(struct wined3d_rendertarget_view *v + + if (!refcount) + { ++ struct wined3d_device *device = view->resource->device; ++ + /* 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); ++ wined3d_cs_emit_view_destroy(device->cs, view); ++ } ++ ++ return refcount; ++} ++ ++/* Ugly hack for ffp_blit_depth_fill that allows destroying a view from inside the ++ * worker thread. */ ++ULONG wined3d_rendertarget_view_decref_worker(struct wined3d_rendertarget_view *view) ++{ ++ ULONG refcount = InterlockedDecrement(&view->refcount); ++ ++ TRACE("%p decreasing refcount to %u.\n", view, refcount); ++ ++ if (!refcount) ++ { ++ /* 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); ++ wined3d_rendertarget_view_destroy(view); + } + + return refcount; +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 0f88961..7d68448 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2699,6 +2699,7 @@ void wined3d_cs_emit_buffer_swap_mem(struct wined3d_cs *cs, struct wined3d_buffe + void wined3d_cs_emit_buffer_invalidate_bo_range(struct wined3d_cs *cs, + struct wined3d_buffer *buffer, UINT offset, UINT size) DECLSPEC_HIDDEN; + void wined3d_cs_emit_buffer_preload(struct wined3d_cs *cs, struct wined3d_buffer *buffer) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_view_destroy(struct wined3d_cs *cs, struct wined3d_rendertarget_view *view) DECLSPEC_HIDDEN; + + /* 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 +@@ -2824,6 +2825,9 @@ static inline struct wined3d_surface *wined3d_rendertarget_view_get_surface( + return surface_from_resource(resource); + } + ++ULONG wined3d_rendertarget_view_decref_worker(struct wined3d_rendertarget_view *view) DECLSPEC_HIDDEN; ++void wined3d_rendertarget_view_destroy(struct wined3d_rendertarget_view *view) DECLSPEC_HIDDEN; ++ + struct wined3d_shader_resource_view + { + LONG refcount; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0132-wined3d-Remove-another-glFinish.patch b/patches/wined3d-CSMT_Main/0132-wined3d-Remove-another-glFinish.patch new file mode 100644 index 00000000..d1efd7fb --- /dev/null +++ b/patches/wined3d-CSMT_Main/0132-wined3d-Remove-another-glFinish.patch @@ -0,0 +1,28 @@ +From 8a0e110ba10657b84aa33a1cd51fe46128062d4d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Sat, 6 Jul 2013 22:08:39 +0200 +Subject: wined3d: Remove another glFinish + +I don't think this is needed any more. +--- + dlls/wined3d/surface.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 43f68c6..1d777e2 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -825,9 +825,7 @@ static void surface_blt_fbo(const struct wined3d_device *device, + dst_rect.left, dst_rect.top, dst_rect.right, dst_rect.bottom, GL_COLOR_BUFFER_BIT, gl_filter); + checkGLcall("glBlitFramebuffer()"); + +- if (wined3d_settings.cs_multithreaded) +- gl_info->gl_ops.gl.p_glFinish(); +- else if (wined3d_settings.strict_draw_ordering ++ if (wined3d_settings.strict_draw_ordering + || (dst_location == WINED3D_LOCATION_DRAWABLE + && dst_surface->container->swapchain->front_buffer == dst_surface->container)) + gl_info->gl_ops.gl.p_glFlush(); +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0133-wined3d-Destroy-vertex-declarations-through-the-CS.patch b/patches/wined3d-CSMT_Main/0133-wined3d-Destroy-vertex-declarations-through-the-CS.patch new file mode 100644 index 00000000..9b952e06 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0133-wined3d-Destroy-vertex-declarations-through-the-CS.patch @@ -0,0 +1,131 @@ +From a26808a39c226fc0f168336becc97ed512029d52 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Wed, 31 Jul 2013 23:06:27 +0200 +Subject: wined3d: Destroy vertex declarations through the CS + +--- + dlls/wined3d/cs.c | 29 +++++++++++++++++++++++++++++ + dlls/wined3d/vertexdeclaration.c | 15 ++++++++------- + dlls/wined3d/wined3d_private.h | 4 ++++ + 3 files changed, 41 insertions(+), 7 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 8e48c55..38063d7 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -79,6 +79,7 @@ enum wined3d_cs_op + WINED3D_CS_OP_UPDATE_TEXTURE, + WINED3D_CS_OP_EVICT_RESOURCE, + WINED3D_CS_OP_VIEW_DESTROY, ++ WINED3D_CS_OP_VDECL_DESTROY, + WINED3D_CS_OP_STOP, + }; + +@@ -456,6 +457,12 @@ struct wined3d_cs_view_destroy + struct wined3d_rendertarget_view *view; + }; + ++struct wined3d_cs_vertex_declaration_destroy ++{ ++ enum wined3d_cs_op opcode; ++ struct wined3d_vertex_declaration *declaration; ++}; ++ + static void wined3d_cs_mt_submit(struct wined3d_cs *cs, size_t size) + { + LONG new_val = (cs->queue.head + size) & (WINED3D_CS_QUEUE_SIZE - 1); +@@ -2251,6 +2258,27 @@ void wined3d_cs_emit_view_destroy(struct wined3d_cs *cs, struct wined3d_renderta + cs->ops->submit(cs, sizeof(*op)); + } + ++static UINT wined3d_cs_exec_vertex_declaration_destroy(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_vertex_declaration_destroy *op = data; ++ ++ wined3d_vertex_declaration_destroy(op->declaration); ++ ++ return sizeof(*op); ++} ++ ++void wined3d_cs_emit_vertex_declaration_destroy(struct wined3d_cs *cs, ++ struct wined3d_vertex_declaration *declaration) ++{ ++ struct wined3d_cs_vertex_declaration_destroy *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_VDECL_DESTROY; ++ op->declaration = declaration; ++ ++ cs->ops->submit(cs, sizeof(*op)); ++} ++ + static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = + { + /* WINED3D_CS_OP_NOP */ wined3d_cs_exec_nop, +@@ -2308,6 +2336,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* 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, + }; + + static inline void *_wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size, BOOL prio) +diff --git a/dlls/wined3d/vertexdeclaration.c b/dlls/wined3d/vertexdeclaration.c +index 3f4d5e4..fc7a110 100644 +--- a/dlls/wined3d/vertexdeclaration.c ++++ b/dlls/wined3d/vertexdeclaration.c +@@ -48,6 +48,12 @@ ULONG CDECL wined3d_vertex_declaration_incref(struct wined3d_vertex_declaration + return refcount; + } + ++void wined3d_vertex_declaration_destroy(struct wined3d_vertex_declaration *declaration) ++{ ++ HeapFree(GetProcessHeap(), 0, declaration->elements); ++ HeapFree(GetProcessHeap(), 0, declaration); ++} ++ + ULONG CDECL wined3d_vertex_declaration_decref(struct wined3d_vertex_declaration *declaration) + { + ULONG refcount = InterlockedDecrement(&declaration->ref); +@@ -56,14 +62,9 @@ ULONG CDECL wined3d_vertex_declaration_decref(struct wined3d_vertex_declaration + + if (!refcount) + { +- if (wined3d_settings.cs_multithreaded) +- { +- FIXME("Waiting for cs.\n"); +- declaration->device->cs->ops->finish(declaration->device->cs); +- } +- HeapFree(GetProcessHeap(), 0, declaration->elements); ++ const struct wined3d_device *device = declaration->device; + declaration->parent_ops->wined3d_object_destroyed(declaration->parent); +- HeapFree(GetProcessHeap(), 0, declaration); ++ wined3d_cs_emit_vertex_declaration_destroy(device->cs, declaration); + } + + return refcount; +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 7d68448..5d3393c 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2499,6 +2499,8 @@ struct wined3d_vertex_declaration + BOOL half_float_conv_needed; + }; + ++void wined3d_vertex_declaration_destroy(struct wined3d_vertex_declaration *declaration) DECLSPEC_HIDDEN; ++ + struct wined3d_saved_states + { + DWORD transform[(HIGHEST_TRANSFORMSTATE >> 5) + 1]; +@@ -2700,6 +2702,8 @@ void wined3d_cs_emit_buffer_invalidate_bo_range(struct wined3d_cs *cs, + struct wined3d_buffer *buffer, UINT offset, UINT size) DECLSPEC_HIDDEN; + void wined3d_cs_emit_buffer_preload(struct wined3d_cs *cs, struct wined3d_buffer *buffer) DECLSPEC_HIDDEN; + void wined3d_cs_emit_view_destroy(struct wined3d_cs *cs, struct wined3d_rendertarget_view *view) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_vertex_declaration_destroy(struct wined3d_cs *cs, ++ struct wined3d_vertex_declaration *declaration) DECLSPEC_HIDDEN; + + /* 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 +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0134-wined3d-Destroy-shaders-through-the-CS.patch b/patches/wined3d-CSMT_Main/0134-wined3d-Destroy-shaders-through-the-CS.patch new file mode 100644 index 00000000..0aa9aeaa --- /dev/null +++ b/patches/wined3d-CSMT_Main/0134-wined3d-Destroy-shaders-through-the-CS.patch @@ -0,0 +1,126 @@ +From 30ad009ccd9e681bab8813c09847c62bd9367916 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Wed, 31 Jul 2013 23:18:28 +0200 +Subject: wined3d: Destroy shaders through the CS + +--- + dlls/wined3d/cs.c | 29 +++++++++++++++++++++++++++++ + dlls/wined3d/shader.c | 12 ++++-------- + dlls/wined3d/wined3d_private.h | 2 ++ + 3 files changed, 35 insertions(+), 8 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 38063d7..21d5b74 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -80,6 +80,7 @@ enum wined3d_cs_op + WINED3D_CS_OP_EVICT_RESOURCE, + WINED3D_CS_OP_VIEW_DESTROY, + WINED3D_CS_OP_VDECL_DESTROY, ++ WINED3D_CS_OP_SHADER_CLEANUP, + WINED3D_CS_OP_STOP, + }; + +@@ -463,6 +464,12 @@ struct wined3d_cs_vertex_declaration_destroy + struct wined3d_vertex_declaration *declaration; + }; + ++struct wined3d_cs_shader_cleanup ++{ ++ enum wined3d_cs_op opcode; ++ struct wined3d_shader *shader; ++}; ++ + static void wined3d_cs_mt_submit(struct wined3d_cs *cs, size_t size) + { + LONG new_val = (cs->queue.head + size) & (WINED3D_CS_QUEUE_SIZE - 1); +@@ -2279,6 +2286,27 @@ void wined3d_cs_emit_vertex_declaration_destroy(struct wined3d_cs *cs, + cs->ops->submit(cs, sizeof(*op)); + } + ++static UINT wined3d_cs_exec_shader_cleanup(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_shader_cleanup *op = data; ++ ++ shader_cleanup(op->shader); ++ HeapFree(GetProcessHeap(), 0, op->shader); ++ ++ return sizeof(*op); ++} ++ ++void wined3d_cs_emit_shader_cleanup(struct wined3d_cs *cs, struct wined3d_shader *shader) ++{ ++ struct wined3d_cs_shader_cleanup *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_SHADER_CLEANUP; ++ op->shader = shader; ++ ++ cs->ops->submit(cs, sizeof(*op)); ++} ++ + static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = + { + /* WINED3D_CS_OP_NOP */ wined3d_cs_exec_nop, +@@ -2337,6 +2365,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* 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, + }; + + static inline void *_wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size, BOOL prio) +diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c +index 0faabaa..8c9be69 100644 +--- a/dlls/wined3d/shader.c ++++ b/dlls/wined3d/shader.c +@@ -1702,7 +1702,7 @@ static void shader_trace_init(const struct wined3d_shader_frontend *fe, void *fe + } + } + +-static void shader_cleanup(struct wined3d_shader *shader) ++void shader_cleanup(struct wined3d_shader *shader) + { + HeapFree(GetProcessHeap(), 0, shader->signature_strings); + shader->device->shader_backend->shader_destroy(shader); +@@ -1957,14 +1957,10 @@ ULONG CDECL wined3d_shader_decref(struct wined3d_shader *shader) + + if (!refcount) + { +- if (wined3d_settings.cs_multithreaded) +- { +- FIXME("Waiting for cs.\n"); +- shader->device->cs->ops->finish(shader->device->cs); +- } +- shader_cleanup(shader); ++ const struct wined3d_device *device = shader->device; ++ + shader->parent_ops->wined3d_object_destroyed(shader->parent); +- HeapFree(GetProcessHeap(), 0, shader); ++ wined3d_cs_emit_shader_cleanup(device->cs, shader); + } + + return refcount; +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 5d3393c..86ee114 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2704,6 +2704,7 @@ void wined3d_cs_emit_buffer_preload(struct wined3d_cs *cs, struct wined3d_buffer + void wined3d_cs_emit_view_destroy(struct wined3d_cs *cs, struct wined3d_rendertarget_view *view) DECLSPEC_HIDDEN; + void wined3d_cs_emit_vertex_declaration_destroy(struct wined3d_cs *cs, + struct wined3d_vertex_declaration *declaration) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_shader_cleanup(struct wined3d_cs *cs, struct wined3d_shader *shader) DECLSPEC_HIDDEN; + + /* 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 +@@ -3103,6 +3104,7 @@ unsigned int shader_find_free_input_register(const struct wined3d_shader_reg_map + void shader_generate_main(const struct wined3d_shader *shader, struct wined3d_shader_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; ++void shader_cleanup(struct wined3d_shader *shader) DECLSPEC_HIDDEN; + + static inline BOOL shader_is_scalar(const struct wined3d_shader_register *reg) + { +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0135-wined3d-Create-VBOs-through-the-command-stream.patch b/patches/wined3d-CSMT_Main/0135-wined3d-Create-VBOs-through-the-command-stream.patch new file mode 100644 index 00000000..11759f3c --- /dev/null +++ b/patches/wined3d-CSMT_Main/0135-wined3d-Create-VBOs-through-the-command-stream.patch @@ -0,0 +1,133 @@ +From 551886caadf25e70d783f9d4584054b7a4fed39d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Wed, 2 Oct 2013 21:47:08 +0200 +Subject: wined3d: Create VBOs through the command stream. + +A stop-gap solution to make fglrx happier until buffers are updated. +--- + dlls/wined3d/buffer.c | 8 ++------ + dlls/wined3d/cs.c | 32 ++++++++++++++++++++++++++++++++ + dlls/wined3d/wined3d_private.h | 3 +++ + 3 files changed, 37 insertions(+), 6 deletions(-) + +diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c +index 81c607d..fc65d3a 100644 +--- a/dlls/wined3d/buffer.c ++++ b/dlls/wined3d/buffer.c +@@ -117,7 +117,7 @@ static void delete_gl_buffer(struct wined3d_buffer *This, const struct wined3d_g + } + + /* Context activation is done by the caller. */ +-static void buffer_create_buffer_object(struct wined3d_buffer *This, struct wined3d_context *context) ++void buffer_create_buffer_object(struct wined3d_buffer *This, struct wined3d_context *context) + { + GLenum gl_usage = GL_STATIC_DRAW_ARB; + GLenum error; +@@ -185,8 +185,6 @@ static void buffer_create_buffer_object(struct wined3d_buffer *This, struct wine + ERR("glBufferDataARB failed with error %s (%#x)\n", debug_glerror(error), error); + goto fail; + } +- if (wined3d_settings.strict_draw_ordering || wined3d_settings.cs_multithreaded) +- gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ + + This->buffer_object_usage = gl_usage; + +@@ -933,9 +931,7 @@ HRESULT CDECL wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UIN + * on buffer creation won't work either. */ + if (buffer->flags & WINED3D_BUFFER_CREATEBO) + { +- context = context_acquire(device, NULL); +- buffer_create_buffer_object(buffer, context); +- context_release(context); ++ wined3d_cs_emit_create_vbo(device->cs, buffer); + buffer->flags &= ~WINED3D_BUFFER_CREATEBO; + } + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 21d5b74..c00d1d3 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -81,6 +81,7 @@ enum wined3d_cs_op + WINED3D_CS_OP_VIEW_DESTROY, + WINED3D_CS_OP_VDECL_DESTROY, + WINED3D_CS_OP_SHADER_CLEANUP, ++ WINED3D_CS_OP_CREATE_VBO, + WINED3D_CS_OP_STOP, + }; + +@@ -470,6 +471,12 @@ struct wined3d_cs_shader_cleanup + struct wined3d_shader *shader; + }; + ++struct wined3d_cs_create_vbo ++{ ++ enum wined3d_cs_op opcode; ++ struct wined3d_buffer *buffer; ++}; ++ + static void wined3d_cs_mt_submit(struct wined3d_cs *cs, size_t size) + { + LONG new_val = (cs->queue.head + size) & (WINED3D_CS_QUEUE_SIZE - 1); +@@ -2307,6 +2314,30 @@ void wined3d_cs_emit_shader_cleanup(struct wined3d_cs *cs, struct wined3d_shader + cs->ops->submit(cs, sizeof(*op)); + } + ++static UINT wined3d_cs_exec_create_vbo(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_create_vbo *op = data; ++ struct wined3d_context *context = context_acquire(cs->device, NULL); ++ ++ buffer_create_buffer_object(op->buffer, context); ++ ++ context_release(context); ++ ++ return sizeof(*op); ++} ++ ++void wined3d_cs_emit_create_vbo(struct wined3d_cs *cs, struct wined3d_buffer *buffer) ++{ ++ struct wined3d_cs_create_vbo *op; ++ ++ op = cs->ops->require_space_prio(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_CREATE_VBO; ++ op->buffer = buffer; ++ ++ cs->ops->submit_prio(cs, sizeof(*op)); ++ cs->ops->finish_prio(cs); ++} ++ + static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = + { + /* WINED3D_CS_OP_NOP */ wined3d_cs_exec_nop, +@@ -2366,6 +2397,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* 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, + }; + + static inline void *_wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size, BOOL prio) +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 86ee114..74e059c 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2705,6 +2705,7 @@ void wined3d_cs_emit_view_destroy(struct wined3d_cs *cs, struct wined3d_renderta + void wined3d_cs_emit_vertex_declaration_destroy(struct wined3d_cs *cs, + struct wined3d_vertex_declaration *declaration) DECLSPEC_HIDDEN; + void wined3d_cs_emit_shader_cleanup(struct wined3d_cs *cs, struct wined3d_shader *shader) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_create_vbo(struct wined3d_cs *cs, struct wined3d_buffer *buffer) DECLSPEC_HIDDEN; + + /* 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 +@@ -2793,6 +2794,8 @@ void buffer_internal_preload(struct wined3d_buffer *buffer, struct wined3d_conte + const struct wined3d_state *state) DECLSPEC_HIDDEN; + 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; + + struct wined3d_rendertarget_view + { +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0136-wined3d-Clean-up-resource-data-through-the-CS.patch b/patches/wined3d-CSMT_Main/0136-wined3d-Clean-up-resource-data-through-the-CS.patch new file mode 100644 index 00000000..82d014af --- /dev/null +++ b/patches/wined3d-CSMT_Main/0136-wined3d-Clean-up-resource-data-through-the-CS.patch @@ -0,0 +1,211 @@ +From 9109cd39e2867e3e9061d1720bde4598111b3d3b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Wed, 2 Oct 2013 22:38:51 +0200 +Subject: wined3d: Clean up resource data through the CS. + +--- + dlls/wined3d/buffer.c | 3 +++ + dlls/wined3d/cs.c | 28 ++++++++++++++++++++++++++++ + dlls/wined3d/resource.c | 15 ++++++++++----- + dlls/wined3d/surface.c | 5 +++++ + dlls/wined3d/texture.c | 4 ++++ + dlls/wined3d/volume.c | 3 +++ + dlls/wined3d/wined3d_private.h | 3 +++ + 7 files changed, 56 insertions(+), 5 deletions(-) + +diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c +index fc65d3a..d968dcb 100644 +--- a/dlls/wined3d/buffer.c ++++ b/dlls/wined3d/buffer.c +@@ -570,6 +570,9 @@ ULONG CDECL wined3d_buffer_decref(struct wined3d_buffer *buffer) + } + + resource_cleanup(&buffer->resource); ++ if (wined3d_settings.cs_multithreaded) ++ buffer->resource.device->cs->ops->finish(buffer->resource.device->cs); ++ + buffer->resource.parent_ops->wined3d_object_destroyed(buffer->resource.parent); + HeapFree(GetProcessHeap(), 0, buffer->maps); + HeapFree(GetProcessHeap(), 0, buffer); +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index c00d1d3..6edd5e3 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -82,6 +82,7 @@ enum wined3d_cs_op + WINED3D_CS_OP_VDECL_DESTROY, + WINED3D_CS_OP_SHADER_CLEANUP, + WINED3D_CS_OP_CREATE_VBO, ++ WINED3D_CS_OP_RESOURCE_CLEANUP, + WINED3D_CS_OP_STOP, + }; + +@@ -477,6 +478,12 @@ struct wined3d_cs_create_vbo + struct wined3d_buffer *buffer; + }; + ++struct wined3d_cs_resource_cleanup ++{ ++ enum wined3d_cs_op opcode; ++ struct wined3d_resource *resource; ++}; ++ + static void wined3d_cs_mt_submit(struct wined3d_cs *cs, size_t size) + { + LONG new_val = (cs->queue.head + size) & (WINED3D_CS_QUEUE_SIZE - 1); +@@ -2338,6 +2345,26 @@ void wined3d_cs_emit_create_vbo(struct wined3d_cs *cs, struct wined3d_buffer *bu + cs->ops->finish_prio(cs); + } + ++static UINT wined3d_cs_exec_resource_cleanup(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_resource_cleanup *op = data; ++ ++ wined3d_resource_cleanup_cs(op->resource); ++ ++ return sizeof(*op); ++} ++ ++void wined3d_cs_emit_resource_cleanup(struct wined3d_cs *cs, struct wined3d_resource *resource) ++{ ++ struct wined3d_cs_resource_cleanup *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_RESOURCE_CLEANUP; ++ op->resource = resource; ++ ++ cs->ops->submit(cs, sizeof(*op)); ++} ++ + static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = + { + /* WINED3D_CS_OP_NOP */ wined3d_cs_exec_nop, +@@ -2398,6 +2425,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* 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, + }; + + static inline void *_wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size, BOOL prio) +diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c +index ef0b213..dd21986 100644 +--- a/dlls/wined3d/resource.c ++++ b/dlls/wined3d/resource.c +@@ -157,6 +157,15 @@ void wined3d_resource_free_bo(struct wined3d_resource *resource) + context_release(context); + } + ++void wined3d_resource_cleanup_cs(struct wined3d_resource *resource) ++{ ++ if (resource->buffer) ++ wined3d_resource_free_bo(resource); ++ ++ wined3d_resource_free_sysmem(resource); ++ resource->map_heap_memory = NULL; ++} ++ + void resource_cleanup(struct wined3d_resource *resource) + { + const struct wined3d *d3d = resource->device->wined3d; +@@ -169,11 +178,7 @@ void resource_cleanup(struct wined3d_resource *resource) + adapter_adjust_memory(resource->device->adapter, (INT64)0 - resource->size); + } + +- if (resource->buffer) +- wined3d_resource_free_bo(resource); +- +- wined3d_resource_free_sysmem(resource); +- resource->map_heap_memory = NULL; ++ wined3d_cs_emit_resource_cleanup(resource->device->cs, resource); + + device_resource_released(resource->device, resource); + } +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 1d777e2..4a1cf30 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -101,9 +101,12 @@ static void surface_cleanup(struct wined3d_surface *surface) + + void wined3d_surface_destroy(struct wined3d_surface *surface) + { ++ struct wined3d_device *device = surface->resource.device; + TRACE("surface %p.\n", surface); + + surface_cleanup(surface); ++ if (wined3d_settings.cs_multithreaded) ++ device->cs->ops->finish(device->cs); + surface->resource.parent_ops->wined3d_object_destroyed(surface->resource.parent); + HeapFree(GetProcessHeap(), 0, surface); + } +@@ -5321,6 +5324,8 @@ static HRESULT surface_init(struct wined3d_surface *surface, struct wined3d_text + { + ERR("Private setup failed, hr %#x.\n", hr); + surface_cleanup(surface); ++ if (wined3d_settings.cs_multithreaded) ++ surface->resource.device->cs->ops->finish(surface->resource.device->cs); + return hr; + } + +diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c +index ea8589a..f7988e5 100644 +--- a/dlls/wined3d/texture.c ++++ b/dlls/wined3d/texture.c +@@ -74,6 +74,8 @@ static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struc + { + ERR("Failed to allocate sub-resource array.\n"); + resource_cleanup(&texture->resource); ++ if (wined3d_settings.cs_multithreaded) ++ texture->resource.device->cs->ops->finish(texture->resource.device->cs); + return E_OUTOFMEMORY; + } + +@@ -153,6 +155,8 @@ static void wined3d_texture_cleanup(struct wined3d_texture *texture) + wined3d_texture_unload_gl_texture(texture); + HeapFree(GetProcessHeap(), 0, texture->sub_resources); + resource_cleanup(&texture->resource); ++ if (wined3d_settings.cs_multithreaded) ++ texture->resource.device->cs->ops->finish(texture->resource.device->cs); + } + + void wined3d_texture_set_swapchain(struct wined3d_texture *texture, struct wined3d_swapchain *swapchain) +diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c +index 34b72d1..218118d 100644 +--- a/dlls/wined3d/volume.c ++++ b/dlls/wined3d/volume.c +@@ -291,9 +291,12 @@ void wined3d_volume_load(struct wined3d_volume *volume, struct wined3d_context * + + void wined3d_volume_destroy(struct wined3d_volume *volume) + { ++ struct wined3d_device *device = volume->resource.device; + TRACE("volume %p.\n", volume); + + resource_cleanup(&volume->resource); ++ if (wined3d_settings.cs_multithreaded) ++ device->cs->ops->finish(device->cs); + volume->resource.parent_ops->wined3d_object_destroyed(volume->resource.parent); + HeapFree(GetProcessHeap(), 0, volume); + } +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 74e059c..f4c269c 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2163,6 +2163,7 @@ void wined3d_resource_changed(struct wined3d_resource *resource, + struct wined3d_gl_bo *swap_buffer, void *swap_heap_memory) DECLSPEC_HIDDEN; + BOOL wined3d_resource_check_block_align(const struct wined3d_resource *resource, + const struct wined3d_box *box) DECLSPEC_HIDDEN; ++void wined3d_resource_cleanup_cs(struct wined3d_resource *resource) DECLSPEC_HIDDEN; + void wined3d_resource_free_bo(struct wined3d_resource *resource) DECLSPEC_HIDDEN; + void wined3d_resource_free_sysmem(struct wined3d_resource *resource) DECLSPEC_HIDDEN; + BYTE *wined3d_resource_get_map_ptr(const struct wined3d_resource *resource, +@@ -2706,6 +2707,8 @@ void wined3d_cs_emit_vertex_declaration_destroy(struct wined3d_cs *cs, + struct wined3d_vertex_declaration *declaration) DECLSPEC_HIDDEN; + void wined3d_cs_emit_shader_cleanup(struct wined3d_cs *cs, struct wined3d_shader *shader) DECLSPEC_HIDDEN; + void wined3d_cs_emit_create_vbo(struct wined3d_cs *cs, struct wined3d_buffer *buffer) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_resource_cleanup(struct wined3d_cs *cs, ++ struct wined3d_resource *resource) DECLSPEC_HIDDEN; + + /* 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 +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0137-wined3d-Clean-up-buffer-resource-data-through-the-CS.patch b/patches/wined3d-CSMT_Main/0137-wined3d-Clean-up-buffer-resource-data-through-the-CS.patch new file mode 100644 index 00000000..1ca24cef --- /dev/null +++ b/patches/wined3d-CSMT_Main/0137-wined3d-Clean-up-buffer-resource-data-through-the-CS.patch @@ -0,0 +1,156 @@ +From 6462e66d6d2229b1755e7689e2b01eee97696676 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Wed, 2 Oct 2013 22:50:08 +0200 +Subject: wined3d: Clean up buffer resource data through the CS. + +--- + dlls/wined3d/buffer.c | 39 ++++++++++++++++++++------------------- + dlls/wined3d/cs.c | 28 ++++++++++++++++++++++++++++ + dlls/wined3d/wined3d_private.h | 2 ++ + 3 files changed, 50 insertions(+), 19 deletions(-) + +diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c +index d968dcb..15ed760 100644 +--- a/dlls/wined3d/buffer.c ++++ b/dlls/wined3d/buffer.c +@@ -545,37 +545,38 @@ static void buffer_unload(struct wined3d_resource *resource) + resource_unload(resource); + } + ++void wined3d_buffer_cleanup_cs(struct wined3d_buffer *buffer) ++{ ++ struct wined3d_context *context; ++ struct wined3d_device *device = buffer->resource.device; ++ ++ if (buffer->buffer_object) ++ { ++ context = context_acquire(device, NULL); ++ delete_gl_buffer(buffer, context->gl_info); ++ context_release(context); ++ ++ HeapFree(GetProcessHeap(), 0, buffer->conversion_map); ++ } ++ ++ HeapFree(GetProcessHeap(), 0, buffer->maps); ++ HeapFree(GetProcessHeap(), 0, buffer); ++} ++ + 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 (wined3d_settings.cs_multithreaded) +- { +- FIXME("Waiting for cs.\n"); +- buffer->resource.device->cs->ops->finish(buffer->resource.device->cs); +- } +- +- 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); +- } ++ struct wined3d_device *device = buffer->resource.device; + + resource_cleanup(&buffer->resource); +- if (wined3d_settings.cs_multithreaded) +- buffer->resource.device->cs->ops->finish(buffer->resource.device->cs); + + buffer->resource.parent_ops->wined3d_object_destroyed(buffer->resource.parent); +- HeapFree(GetProcessHeap(), 0, buffer->maps); +- HeapFree(GetProcessHeap(), 0, buffer); ++ wined3d_cs_emit_buffer_cleanup(device->cs, buffer); + } + + return refcount; +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 6edd5e3..40cd85d 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -83,6 +83,7 @@ enum wined3d_cs_op + WINED3D_CS_OP_SHADER_CLEANUP, + WINED3D_CS_OP_CREATE_VBO, + WINED3D_CS_OP_RESOURCE_CLEANUP, ++ WINED3D_CS_OP_BUFFER_CLEANUP, + WINED3D_CS_OP_STOP, + }; + +@@ -484,6 +485,12 @@ struct wined3d_cs_resource_cleanup + struct wined3d_resource *resource; + }; + ++struct wined3d_cs_buffer_cleanup ++{ ++ enum wined3d_cs_op opcode; ++ struct wined3d_buffer *buffer; ++}; ++ + static void wined3d_cs_mt_submit(struct wined3d_cs *cs, size_t size) + { + LONG new_val = (cs->queue.head + size) & (WINED3D_CS_QUEUE_SIZE - 1); +@@ -2365,6 +2372,26 @@ void wined3d_cs_emit_resource_cleanup(struct wined3d_cs *cs, struct wined3d_reso + cs->ops->submit(cs, sizeof(*op)); + } + ++static UINT wined3d_cs_exec_buffer_cleanup(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_buffer_cleanup *op = data; ++ ++ wined3d_buffer_cleanup_cs(op->buffer); ++ ++ return sizeof(*op); ++} ++ ++void wined3d_cs_emit_buffer_cleanup(struct wined3d_cs *cs, struct wined3d_buffer *buffer) ++{ ++ struct wined3d_cs_buffer_cleanup *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_BUFFER_CLEANUP; ++ op->buffer = buffer; ++ ++ cs->ops->submit(cs, sizeof(*op)); ++} ++ + static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = + { + /* WINED3D_CS_OP_NOP */ wined3d_cs_exec_nop, +@@ -2426,6 +2453,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* 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, + }; + + static inline void *_wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size, BOOL prio) +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index f4c269c..76c0708 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2709,6 +2709,7 @@ void wined3d_cs_emit_shader_cleanup(struct wined3d_cs *cs, struct wined3d_shader + void wined3d_cs_emit_create_vbo(struct wined3d_cs *cs, struct wined3d_buffer *buffer) DECLSPEC_HIDDEN; + void wined3d_cs_emit_resource_cleanup(struct wined3d_cs *cs, + struct wined3d_resource *resource) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_buffer_cleanup(struct wined3d_cs *cs, struct wined3d_buffer *buffer) DECLSPEC_HIDDEN; + + /* 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 +@@ -2799,6 +2800,7 @@ void buffer_invalidate_bo_range(struct wined3d_buffer *This, UINT offset, UINT s + 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; + + struct wined3d_rendertarget_view + { +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0138-wined3d-Clean-up-volume-resource-data-through-the-CS.patch b/patches/wined3d-CSMT_Main/0138-wined3d-Clean-up-volume-resource-data-through-the-CS.patch new file mode 100644 index 00000000..aaa4e6a4 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0138-wined3d-Clean-up-volume-resource-data-through-the-CS.patch @@ -0,0 +1,122 @@ +From 6237370d85227ef7db8888705128156918fcafc3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Wed, 2 Oct 2013 22:54:57 +0200 +Subject: wined3d: Clean up volume resource data through the CS. + +--- + dlls/wined3d/cs.c | 28 ++++++++++++++++++++++++++++ + dlls/wined3d/volume.c | 9 ++++++--- + dlls/wined3d/wined3d_private.h | 2 ++ + 3 files changed, 36 insertions(+), 3 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 40cd85d..9cba57b 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -84,6 +84,7 @@ enum wined3d_cs_op + WINED3D_CS_OP_CREATE_VBO, + WINED3D_CS_OP_RESOURCE_CLEANUP, + WINED3D_CS_OP_BUFFER_CLEANUP, ++ WINED3D_CS_OP_VOLUME_CLEANUP, + WINED3D_CS_OP_STOP, + }; + +@@ -491,6 +492,12 @@ struct wined3d_cs_buffer_cleanup + struct wined3d_buffer *buffer; + }; + ++struct wined3d_cs_volume_cleanup ++{ ++ enum wined3d_cs_op opcode; ++ struct wined3d_volume *volume; ++}; ++ + static void wined3d_cs_mt_submit(struct wined3d_cs *cs, size_t size) + { + LONG new_val = (cs->queue.head + size) & (WINED3D_CS_QUEUE_SIZE - 1); +@@ -2392,6 +2399,26 @@ void wined3d_cs_emit_buffer_cleanup(struct wined3d_cs *cs, struct wined3d_buffer + cs->ops->submit(cs, sizeof(*op)); + } + ++static UINT wined3d_cs_exec_volume_cleanup(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_volume_cleanup *op = data; ++ ++ wined3d_volume_cleanup_cs(op->volume); ++ ++ return sizeof(*op); ++} ++ ++void wined3d_cs_emit_volume_cleanup(struct wined3d_cs *cs, struct wined3d_volume *volume) ++{ ++ struct wined3d_cs_volume_cleanup *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_VOLUME_CLEANUP; ++ op->volume = volume; ++ ++ cs->ops->submit(cs, sizeof(*op)); ++} ++ + static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = + { + /* WINED3D_CS_OP_NOP */ wined3d_cs_exec_nop, +@@ -2454,6 +2481,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* 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, + }; + + static inline void *_wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size, BOOL prio) +diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c +index 218118d..a30acab 100644 +--- a/dlls/wined3d/volume.c ++++ b/dlls/wined3d/volume.c +@@ -295,10 +295,8 @@ void wined3d_volume_destroy(struct wined3d_volume *volume) + TRACE("volume %p.\n", volume); + + resource_cleanup(&volume->resource); +- if (wined3d_settings.cs_multithreaded) +- device->cs->ops->finish(device->cs); + volume->resource.parent_ops->wined3d_object_destroyed(volume->resource.parent); +- HeapFree(GetProcessHeap(), 0, volume); ++ wined3d_cs_emit_volume_cleanup(device->cs, volume); + } + + static void volume_unload(struct wined3d_resource *resource) +@@ -339,6 +337,11 @@ ULONG CDECL wined3d_volume_incref(struct wined3d_volume *volume) + return wined3d_texture_incref(volume->container); + } + ++void wined3d_volume_cleanup_cs(struct wined3d_volume *volume) ++{ ++ HeapFree(GetProcessHeap(), 0, volume); ++} ++ + ULONG CDECL wined3d_volume_decref(struct wined3d_volume *volume) + { + TRACE("Forwarding to container %p.\n", volume->container); +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 76c0708..2b808dd 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2343,6 +2343,7 @@ void wined3d_volume_load(struct wined3d_volume *volume, struct wined3d_context * + BOOL srgb_mode) DECLSPEC_HIDDEN; + void wined3d_volume_upload_data(struct wined3d_volume *volume, const struct wined3d_context *context, + const struct wined3d_bo_address *data) DECLSPEC_HIDDEN; ++void wined3d_volume_cleanup_cs(struct wined3d_volume *volume) DECLSPEC_HIDDEN; + + struct wined3d_surface_dib + { +@@ -2710,6 +2711,7 @@ void wined3d_cs_emit_create_vbo(struct wined3d_cs *cs, struct wined3d_buffer *bu + void wined3d_cs_emit_resource_cleanup(struct wined3d_cs *cs, + struct wined3d_resource *resource) DECLSPEC_HIDDEN; + void wined3d_cs_emit_buffer_cleanup(struct wined3d_cs *cs, struct wined3d_buffer *buffer) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_volume_cleanup(struct wined3d_cs *cs, struct wined3d_volume *volume) DECLSPEC_HIDDEN; + + /* 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 +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0139-wined3d-Clean-up-surfaces-through-the-cs.patch b/patches/wined3d-CSMT_Main/0139-wined3d-Clean-up-surfaces-through-the-cs.patch new file mode 100644 index 00000000..085b18f2 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0139-wined3d-Clean-up-surfaces-through-the-cs.patch @@ -0,0 +1,178 @@ +From ffa89bb6de1ecc4769b6aae7f0c66b1c18296c21 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Sun, 6 Oct 2013 16:12:24 +0200 +Subject: wined3d: Clean up surfaces through the cs. + +--- + dlls/wined3d/cs.c | 28 ++++++++++++++++++++++++++++ + dlls/wined3d/surface.c | 37 ++++++++++++++++--------------------- + dlls/wined3d/wined3d_private.h | 2 ++ + 3 files changed, 46 insertions(+), 21 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 9cba57b..7675214 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -85,6 +85,7 @@ enum wined3d_cs_op + WINED3D_CS_OP_RESOURCE_CLEANUP, + WINED3D_CS_OP_BUFFER_CLEANUP, + WINED3D_CS_OP_VOLUME_CLEANUP, ++ WINED3D_CS_OP_SURFACE_CLEANUP, + WINED3D_CS_OP_STOP, + }; + +@@ -498,6 +499,12 @@ struct wined3d_cs_volume_cleanup + struct wined3d_volume *volume; + }; + ++struct wined3d_cs_surface_cleanup ++{ ++ enum wined3d_cs_op opcode; ++ struct wined3d_surface *surface; ++}; ++ + static void wined3d_cs_mt_submit(struct wined3d_cs *cs, size_t size) + { + LONG new_val = (cs->queue.head + size) & (WINED3D_CS_QUEUE_SIZE - 1); +@@ -2419,6 +2426,26 @@ void wined3d_cs_emit_volume_cleanup(struct wined3d_cs *cs, struct wined3d_volume + cs->ops->submit(cs, sizeof(*op)); + } + ++static UINT wined3d_cs_exec_surface_cleanup(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_surface_cleanup *op = data; ++ ++ wined3d_surface_cleanup_cs(op->surface); ++ ++ return sizeof(*op); ++} ++ ++void wined3d_cs_emit_surface_cleanup(struct wined3d_cs *cs, struct wined3d_surface *surface) ++{ ++ struct wined3d_cs_surface_cleanup *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_SURFACE_CLEANUP; ++ op->surface = surface; ++ ++ cs->ops->submit(cs, sizeof(*op)); ++} ++ + static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = + { + /* WINED3D_CS_OP_NOP */ wined3d_cs_exec_nop, +@@ -2482,6 +2509,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* 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, + }; + + static inline void *_wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size, BOOL prio) +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 4a1cf30..4d8bd1c 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -36,20 +36,10 @@ WINE_DECLARE_DEBUG_CHANNEL(d3d); + + #define MAXLOCKCOUNT 50 /* After this amount of locks do not free the sysmem copy. */ + +-static void surface_cleanup(struct wined3d_surface *surface) +-{ +- struct wined3d_surface *overlay, *cur; +- +- TRACE("surface %p.\n", surface); +- +- if (wined3d_settings.cs_multithreaded) +- { +- FIXME("Waiting for cs.\n"); +- surface->resource.device->cs->ops->finish(surface->resource.device->cs); +- } + +- if (surface->resource.buffer || surface->rb_multisample +- || surface->rb_resolved || !list_empty(&surface->renderbuffers)) ++void wined3d_surface_cleanup_cs(struct wined3d_surface *surface) ++{ ++ if (surface->rb_multisample || surface->rb_resolved || !list_empty(&surface->renderbuffers)) + { + struct wined3d_renderbuffer_entry *entry, *entry2; + const struct wined3d_gl_info *gl_info; +@@ -87,6 +77,16 @@ static void surface_cleanup(struct wined3d_surface *surface) + surface->resource.bitmap_data = NULL; + } + ++ TRACE("Destroyed surface %p.\n", surface); ++ HeapFree(GetProcessHeap(), 0, surface); ++} ++ ++static void surface_cleanup(struct wined3d_surface *surface) ++{ ++ struct wined3d_surface *overlay, *cur; ++ ++ TRACE("surface %p.\n", surface); ++ + if (surface->overlay_dest) + list_remove(&surface->overlay_entry); + +@@ -97,18 +97,15 @@ static void surface_cleanup(struct wined3d_surface *surface) + } + + resource_cleanup(&surface->resource); ++ wined3d_cs_emit_surface_cleanup(surface->resource.device->cs, surface); + } + + void wined3d_surface_destroy(struct wined3d_surface *surface) + { +- struct wined3d_device *device = surface->resource.device; + TRACE("surface %p.\n", surface); + +- surface_cleanup(surface); +- if (wined3d_settings.cs_multithreaded) +- device->cs->ops->finish(device->cs); + surface->resource.parent_ops->wined3d_object_destroyed(surface->resource.parent); +- HeapFree(GetProcessHeap(), 0, surface); ++ surface_cleanup(surface); + } + + void surface_get_drawable_size(const struct wined3d_surface *surface, const struct wined3d_context *context, +@@ -5324,8 +5321,6 @@ static HRESULT surface_init(struct wined3d_surface *surface, struct wined3d_text + { + ERR("Private setup failed, hr %#x.\n", hr); + surface_cleanup(surface); +- if (wined3d_settings.cs_multithreaded) +- surface->resource.device->cs->ops->finish(surface->resource.device->cs); + return hr; + } + +@@ -5368,7 +5363,7 @@ HRESULT wined3d_surface_create(struct wined3d_texture *container, const struct w + if (FAILED(hr = surface_init(object, container, desc, target, level, layer, flags))) + { + WARN("Failed to initialize surface, returning %#x.\n", hr); +- HeapFree(GetProcessHeap(), 0, object); ++ /* The command stream takes care of freeing the memory. */ + return hr; + } + +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 2b808dd..afb31c2 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2455,6 +2455,7 @@ void surface_blt_ugly(struct wined3d_surface *dst_surface, const RECT *dst_rect_ + struct wined3d_surface *src_surface, const RECT *src_rect_in, DWORD flags, + const WINEDDBLTFX *fx, enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN; + BOOL surface_check_block_align(struct wined3d_surface *surface, const RECT *rect) DECLSPEC_HIDDEN; ++void wined3d_surface_cleanup_cs(struct wined3d_surface *surface) DECLSPEC_HIDDEN; + + 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; +@@ -2712,6 +2713,7 @@ void wined3d_cs_emit_resource_cleanup(struct wined3d_cs *cs, + struct wined3d_resource *resource) DECLSPEC_HIDDEN; + void wined3d_cs_emit_buffer_cleanup(struct wined3d_cs *cs, struct wined3d_buffer *buffer) DECLSPEC_HIDDEN; + void wined3d_cs_emit_volume_cleanup(struct wined3d_cs *cs, struct wined3d_volume *volume) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_surface_cleanup(struct wined3d_cs *cs, struct wined3d_surface *surface) DECLSPEC_HIDDEN; + + /* 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 +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0140-wined3d-Clean-up-texture-resources-through-the-cs.patch b/patches/wined3d-CSMT_Main/0140-wined3d-Clean-up-texture-resources-through-the-cs.patch new file mode 100644 index 00000000..4be13f5d --- /dev/null +++ b/patches/wined3d-CSMT_Main/0140-wined3d-Clean-up-texture-resources-through-the-cs.patch @@ -0,0 +1,291 @@ +From 92b80eca71961fa3669d9da8cb64a62e6f556184 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Sun, 6 Oct 2013 16:20:32 +0200 +Subject: wined3d: Clean up texture resources through the cs. + +--- + dlls/wined3d/cs.c | 28 ++++++++++++++++++++++++++++ + dlls/wined3d/texture.c | 39 +++++++++++++++++++++++++++++++-------- + dlls/wined3d/wined3d_private.h | 2 ++ + 3 files changed, 61 insertions(+), 8 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 7675214..5e4aa53 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -86,6 +86,7 @@ enum wined3d_cs_op + WINED3D_CS_OP_BUFFER_CLEANUP, + WINED3D_CS_OP_VOLUME_CLEANUP, + WINED3D_CS_OP_SURFACE_CLEANUP, ++ WINED3D_CS_OP_TEXTURE_CLEANUP, + WINED3D_CS_OP_STOP, + }; + +@@ -505,6 +506,12 @@ struct wined3d_cs_surface_cleanup + struct wined3d_surface *surface; + }; + ++struct wined3d_cs_texture_cleanup ++{ ++ enum wined3d_cs_op opcode; ++ struct wined3d_texture *texture; ++}; ++ + static void wined3d_cs_mt_submit(struct wined3d_cs *cs, size_t size) + { + LONG new_val = (cs->queue.head + size) & (WINED3D_CS_QUEUE_SIZE - 1); +@@ -2446,6 +2453,26 @@ void wined3d_cs_emit_surface_cleanup(struct wined3d_cs *cs, struct wined3d_surfa + cs->ops->submit(cs, sizeof(*op)); + } + ++static UINT wined3d_cs_exec_texture_cleanup(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_texture_cleanup *op = data; ++ ++ wined3d_texture_cleanup_cs(op->texture); ++ ++ return sizeof(*op); ++} ++ ++void wined3d_cs_emit_texture_cleanup(struct wined3d_cs *cs, struct wined3d_texture *texture) ++{ ++ struct wined3d_cs_texture_cleanup *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_TEXTURE_CLEANUP; ++ op->texture = texture; ++ ++ cs->ops->submit(cs, sizeof(*op)); ++} ++ + static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = + { + /* WINED3D_CS_OP_NOP */ wined3d_cs_exec_nop, +@@ -2510,6 +2537,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* 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, + }; + + static inline void *_wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size, BOOL prio) +diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c +index f7988e5..f055d5e 100644 +--- a/dlls/wined3d/texture.c ++++ b/dlls/wined3d/texture.c +@@ -131,17 +131,26 @@ static void wined3d_texture_unload_gl_texture(struct wined3d_texture *texture) + resource_unload(&texture->resource); + } + ++void wined3d_texture_cleanup_cs(struct wined3d_texture *texture) ++{ ++ wined3d_texture_unload_gl_texture(texture); ++ HeapFree(GetProcessHeap(), 0, texture->sub_resources); ++ HeapFree(GetProcessHeap(), 0, texture); ++} ++ + static void wined3d_texture_cleanup(struct wined3d_texture *texture) + { + UINT sub_count = texture->level_count * texture->layer_count; + UINT i; ++ struct wined3d_device *device = texture->resource.device; + + TRACE("texture %p.\n", texture); + ++ /* Because sub_resource_cleanup interferes with GL resources */ + if (wined3d_settings.cs_multithreaded) + { + FIXME("Waiting for cs.\n"); +- texture->resource.device->cs->ops->finish(texture->resource.device->cs); ++ device->cs->ops->finish(device->cs); + } + + for (i = 0; i < sub_count; ++i) +@@ -152,11 +161,8 @@ static void wined3d_texture_cleanup(struct wined3d_texture *texture) + texture->texture_ops->texture_sub_resource_cleanup(sub_resource); + } + +- wined3d_texture_unload_gl_texture(texture); +- HeapFree(GetProcessHeap(), 0, texture->sub_resources); + resource_cleanup(&texture->resource); +- if (wined3d_settings.cs_multithreaded) +- texture->resource.device->cs->ops->finish(texture->resource.device->cs); ++ wined3d_cs_emit_texture_cleanup(device->cs, texture); + } + + void wined3d_texture_set_swapchain(struct wined3d_texture *texture, struct wined3d_swapchain *swapchain) +@@ -523,9 +529,10 @@ ULONG CDECL wined3d_texture_decref(struct wined3d_texture *texture) + + if (!refcount) + { ++ void *parent = texture->resource.parent; ++ const struct wined3d_parent_ops *parent_ops = texture->resource.parent_ops; + wined3d_texture_cleanup(texture); +- texture->resource.parent_ops->wined3d_object_destroyed(texture->resource.parent); +- HeapFree(GetProcessHeap(), 0, texture); ++ parent_ops->wined3d_object_destroyed(parent); + } + + return refcount; +@@ -1040,12 +1047,14 @@ static HRESULT cubetexture_init(struct wined3d_texture *texture, const struct wi + if (WINED3DFMT_UNKNOWN >= desc->format) + { + WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture); ++ HeapFree(GetProcessHeap(), 0, texture); + return WINED3DERR_INVALIDCALL; + } + + if (!gl_info->supported[ARB_TEXTURE_CUBE_MAP] && desc->pool != WINED3D_POOL_SCRATCH) + { + WARN("(%p) : Tried to create not supported cube texture.\n", texture); ++ HeapFree(GetProcessHeap(), 0, texture); + return WINED3DERR_INVALIDCALL; + } + +@@ -1055,12 +1064,14 @@ static HRESULT cubetexture_init(struct wined3d_texture *texture, const struct wi + if (!gl_info->supported[SGIS_GENERATE_MIPMAP]) + { + WARN("No mipmap generation support, returning D3DERR_INVALIDCALL.\n"); ++ HeapFree(GetProcessHeap(), 0, texture); + return WINED3DERR_INVALIDCALL; + } + + if (levels > 1) + { + WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL.\n"); ++ HeapFree(GetProcessHeap(), 0, texture); + return WINED3DERR_INVALIDCALL; + } + +@@ -1088,6 +1099,7 @@ static HRESULT cubetexture_init(struct wined3d_texture *texture, const struct wi + else + { + WARN("Attempted to create a NPOT cube texture (edge length %u) without GL support.\n", desc->width); ++ HeapFree(GetProcessHeap(), 0, texture); + return WINED3DERR_INVALIDCALL; + } + } +@@ -1097,6 +1109,7 @@ static HRESULT cubetexture_init(struct wined3d_texture *texture, const struct wi + surface_flags, device, parent, parent_ops, &texture_resource_ops))) + { + WARN("Failed to initialize texture, returning %#x\n", hr); ++ HeapFree(GetProcessHeap(), 0, texture); + return hr; + } + +@@ -1159,6 +1172,7 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3 + if (WINED3DFMT_UNKNOWN >= desc->format) + { + WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture); ++ HeapFree(GetProcessHeap(), 0, texture); + return WINED3DERR_INVALIDCALL; + } + +@@ -1189,6 +1203,7 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3 + else + { + WARN("Attempted to create a mipmapped NPOT texture without unconditional NPOT support.\n"); ++ HeapFree(GetProcessHeap(), 0, texture); + return WINED3DERR_INVALIDCALL; + } + } +@@ -1201,12 +1216,14 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3 + if (!gl_info->supported[SGIS_GENERATE_MIPMAP]) + { + WARN("No mipmap generation support, returning WINED3DERR_INVALIDCALL.\n"); ++ HeapFree(GetProcessHeap(), 0, texture); + return WINED3DERR_INVALIDCALL; + } + + if (levels > 1) + { + WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning WINED3DERR_INVALIDCALL.\n"); ++ HeapFree(GetProcessHeap(), 0, texture); + return WINED3DERR_INVALIDCALL; + } + +@@ -1222,6 +1239,7 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3 + surface_flags, device, parent, parent_ops, &texture_resource_ops))) + { + WARN("Failed to initialize texture, returning %#x.\n", hr); ++ HeapFree(GetProcessHeap(), 0, texture); + return hr; + } + +@@ -1382,12 +1400,14 @@ static HRESULT volumetexture_init(struct wined3d_texture *texture, const struct + if (WINED3DFMT_UNKNOWN >= desc->format) + { + WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n", texture); ++ HeapFree(GetProcessHeap(), 0, texture); + return WINED3DERR_INVALIDCALL; + } + + if (!gl_info->supported[EXT_TEXTURE3D]) + { + WARN("(%p) : Texture cannot be created - no volume texture support.\n", texture); ++ HeapFree(GetProcessHeap(), 0, texture); + return WINED3DERR_INVALIDCALL; + } + +@@ -1397,12 +1417,14 @@ static HRESULT volumetexture_init(struct wined3d_texture *texture, const struct + if (!gl_info->supported[SGIS_GENERATE_MIPMAP]) + { + WARN("No mipmap generation support, returning D3DERR_INVALIDCALL.\n"); ++ HeapFree(GetProcessHeap(), 0, texture); + return WINED3DERR_INVALIDCALL; + } + + if (levels > 1) + { + WARN("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL.\n"); ++ HeapFree(GetProcessHeap(), 0, texture); + return WINED3DERR_INVALIDCALL; + } + +@@ -1437,6 +1459,7 @@ static HRESULT volumetexture_init(struct wined3d_texture *texture, const struct + { + WARN("Attempted to create a NPOT volume texture (%u, %u, %u) without GL support.\n", + desc->width, desc->height, desc->depth); ++ HeapFree(GetProcessHeap(), 0, texture); + return WINED3DERR_INVALIDCALL; + } + } +@@ -1446,6 +1469,7 @@ static HRESULT volumetexture_init(struct wined3d_texture *texture, const struct + 0, device, parent, parent_ops, &texture_resource_ops))) + { + WARN("Failed to initialize texture, returning %#x.\n", hr); ++ HeapFree(GetProcessHeap(), 0, texture); + return hr; + } + +@@ -1516,7 +1540,6 @@ HRESULT CDECL wined3d_texture_create(struct wined3d_device *device, const struct + if (FAILED(hr)) + { + WARN("Failed to initialize texture, returning %#x.\n", hr); +- HeapFree(GetProcessHeap(), 0, object); + return hr; + } + +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index afb31c2..6382375 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2293,6 +2293,7 @@ static inline struct gl_texture *wined3d_texture_get_gl_texture(struct wined3d_t + void wined3d_texture_apply_state_changes(struct wined3d_texture *texture, + const DWORD samplerStates[WINED3D_HIGHEST_SAMPLER_STATE + 1], + const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN; ++void wined3d_texture_cleanup_cs(struct wined3d_texture *texture) DECLSPEC_HIDDEN; + 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, +@@ -2714,6 +2715,7 @@ void wined3d_cs_emit_resource_cleanup(struct wined3d_cs *cs, + void wined3d_cs_emit_buffer_cleanup(struct wined3d_cs *cs, struct wined3d_buffer *buffer) DECLSPEC_HIDDEN; + void wined3d_cs_emit_volume_cleanup(struct wined3d_cs *cs, struct wined3d_volume *volume) DECLSPEC_HIDDEN; + void wined3d_cs_emit_surface_cleanup(struct wined3d_cs *cs, struct wined3d_surface *surface) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_texture_cleanup(struct wined3d_cs *cs, struct wined3d_texture *texture) DECLSPEC_HIDDEN; + + /* 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 +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0141-wined3d-Unload-resources-through-the-CS-in-uninit_3d.patch b/patches/wined3d-CSMT_Main/0141-wined3d-Unload-resources-through-the-CS-in-uninit_3d.patch new file mode 100644 index 00000000..7b0080fa --- /dev/null +++ b/patches/wined3d-CSMT_Main/0141-wined3d-Unload-resources-through-the-CS-in-uninit_3d.patch @@ -0,0 +1,29 @@ +From a2b1d967f8c0ee199803ba6e7ebb0b07c26a65f0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Wed, 2 Oct 2013 23:28:56 +0200 +Subject: wined3d: Unload resources through the CS in uninit_3d. + +--- + dlls/wined3d/device.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index f5cb7bd..28819af 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -1050,9 +1050,10 @@ HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device) + LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &device->resources, struct wined3d_resource, resource_list_entry) + { + TRACE("Unloading resource %p.\n", resource); +- +- resource->resource_ops->resource_unload(resource); ++ wined3d_cs_emit_evict_resource(device->cs, resource); + } ++ if (wined3d_settings.cs_multithreaded) ++ device->cs->ops->finish(device->cs); + + /* Destroy the depth blt resources, they will be invalid after the reset. Also free shader + * private data, it might contain opengl pointers +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0142-wined3d-Unload-resources-through-the-CS-in-device_re.patch b/patches/wined3d-CSMT_Main/0142-wined3d-Unload-resources-through-the-CS-in-device_re.patch new file mode 100644 index 00000000..4c4dbf7e --- /dev/null +++ b/patches/wined3d-CSMT_Main/0142-wined3d-Unload-resources-through-the-CS-in-device_re.patch @@ -0,0 +1,44 @@ +From d2b010c4c1c08d71ed6e2e4257db236535c20deb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Wed, 2 Oct 2013 23:40:20 +0200 +Subject: wined3d: Unload resources through the CS in device_reset. + +--- + dlls/wined3d/device.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index 28819af..2410547 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -4228,21 +4228,23 @@ static void delete_opengl_contexts(struct wined3d_device *device, struct wined3d + struct wined3d_context *context; + struct wined3d_shader *shader; + +- context = context_acquire(device, NULL); +- gl_info = context->gl_info; +- + LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &device->resources, struct wined3d_resource, resource_list_entry) + { + TRACE("Unloading resource %p.\n", resource); + +- resource->resource_ops->resource_unload(resource); ++ wined3d_cs_emit_evict_resource(device->cs, resource); + } ++ if (wined3d_settings.cs_multithreaded) ++ device->cs->ops->finish(device->cs); + + LIST_FOR_EACH_ENTRY(shader, &device->shaders, struct wined3d_shader, shader_list_entry) + { + device->shader_backend->shader_destroy(shader); + } + ++ context = context_acquire(device, NULL); ++ gl_info = context->gl_info; ++ + if (device->depth_blt_texture) + { + gl_info->gl_ops.gl.p_glDeleteTextures(1, &device->depth_blt_texture); +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0143-wined3d-Don-t-glFinish-after-a-depth-buffer-blit.patch b/patches/wined3d-CSMT_Main/0143-wined3d-Don-t-glFinish-after-a-depth-buffer-blit.patch new file mode 100644 index 00000000..3dacf186 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0143-wined3d-Don-t-glFinish-after-a-depth-buffer-blit.patch @@ -0,0 +1,27 @@ +From 81f901210e683ac2a2193957849497031f424545 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 3 Oct 2013 17:39:08 +0200 +Subject: wined3d: Don't glFinish after a depth buffer blit. + +--- + dlls/wined3d/surface.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 4d8bd1c..3c5489f 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -694,9 +694,7 @@ static void surface_depth_blt_fbo(const struct wined3d_device *device, + dst_rect->left, dst_rect->top, dst_rect->right, dst_rect->bottom, gl_mask, GL_NEAREST); + checkGLcall("glBlitFramebuffer()"); + +- if (wined3d_settings.cs_multithreaded) +- gl_info->gl_ops.gl.p_glFinish(); +- else if (wined3d_settings.strict_draw_ordering) ++ if (wined3d_settings.strict_draw_ordering) + gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ + + context_release(context); +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0144-wined3d-Remove-software-cursor-support.patch b/patches/wined3d-CSMT_Main/0144-wined3d-Remove-software-cursor-support.patch new file mode 100644 index 00000000..7427de69 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0144-wined3d-Remove-software-cursor-support.patch @@ -0,0 +1,190 @@ +From 3eb3def034aaacfd9f65b3f6f5f750cccbbf6c42 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 3 Oct 2013 19:23:24 +0200 +Subject: wined3d: Remove software cursor support. + +This has been broken since quite some time and only serves to crash fglrx by acquiring a context +in the main thread. + +FIXME: Make sure wined3d_device_show_cursor returns the correct value if a software cursor is set. +--- + dlls/wined3d/device.c | 83 +----------------------------------------- + dlls/wined3d/swapchain.c | 21 ----------- + dlls/wined3d/wined3d_private.h | 1 - + 3 files changed, 2 insertions(+), 103 deletions(-) + +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index 2410547..b3f75ba 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -1023,8 +1023,6 @@ HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device) + + if (device->logo_texture) + wined3d_texture_decref(device->logo_texture); +- if (device->cursor_texture) +- wined3d_texture_decref(device->cursor_texture); + + /* Release the buffers (with sanity checks). + * FIXME: Move this move into a separate patch. I think the idea +@@ -3984,77 +3982,12 @@ void CDECL wined3d_device_set_depth_stencil_view(struct wined3d_device *device, + wined3d_rendertarget_view_decref(prev); + } + +-static struct wined3d_texture *wined3d_device_create_cursor_texture(struct wined3d_device *device, +- struct wined3d_surface *cursor_image) +-{ +- struct wined3d_resource_desc desc; +- struct wined3d_map_desc map_desc; +- struct wined3d_texture *texture; +- struct wined3d_surface *surface; +- BYTE *src_data, *dst_data; +- unsigned int src_pitch; +- unsigned int i; +- +- if (FAILED(wined3d_surface_map(cursor_image, &map_desc, NULL, WINED3D_MAP_READONLY))) +- { +- ERR("Failed to map source surface.\n"); +- return NULL; +- } +- +- src_pitch = map_desc.row_pitch; +- src_data = map_desc.data; +- +- desc.resource_type = WINED3D_RTYPE_TEXTURE; +- desc.format = WINED3DFMT_B8G8R8A8_UNORM; +- desc.multisample_type = WINED3D_MULTISAMPLE_NONE; +- desc.multisample_quality = 0; +- desc.usage = WINED3DUSAGE_DYNAMIC; +- desc.pool = WINED3D_POOL_DEFAULT; +- desc.width = cursor_image->resource.width; +- desc.height = cursor_image->resource.height; +- desc.depth = 1; +- desc.size = 0; +- +- if (FAILED(wined3d_texture_create(device, &desc, 1, WINED3D_SURFACE_MAPPABLE, +- NULL, &wined3d_null_parent_ops, &texture))) +- { +- ERR("Failed to create cursor texture.\n"); +- wined3d_surface_unmap(cursor_image); +- return NULL; +- } +- +- surface = surface_from_resource(wined3d_texture_get_sub_resource(texture, 0)); +- if (FAILED(wined3d_surface_map(surface, &map_desc, NULL, WINED3D_MAP_DISCARD))) +- { +- ERR("Failed to map destination surface.\n"); +- wined3d_texture_decref(texture); +- wined3d_surface_unmap(cursor_image); +- return NULL; +- } +- +- dst_data = map_desc.data; +- +- for (i = 0; i < desc.height; ++i) +- memcpy(&dst_data[map_desc.row_pitch * i], &src_data[src_pitch * i], desc.width * 4); +- +- wined3d_surface_unmap(surface); +- wined3d_surface_unmap(cursor_image); +- +- return texture; +-} +- + HRESULT CDECL wined3d_device_set_cursor_properties(struct wined3d_device *device, + UINT x_hotspot, UINT y_hotspot, struct wined3d_surface *cursor_image) + { + TRACE("device %p, x_hotspot %u, y_hotspot %u, cursor_image %p.\n", + device, x_hotspot, y_hotspot, cursor_image); + +- if (device->cursor_texture) +- { +- wined3d_texture_decref(device->cursor_texture); +- device->cursor_texture = NULL; +- } +- + if (cursor_image) + { + struct wined3d_display_mode mode; +@@ -4089,11 +4022,8 @@ HRESULT CDECL wined3d_device_set_cursor_properties(struct wined3d_device *device + * release it after setting the cursor image. Windows doesn't + * addref the set surface, so we can't do this either without + * creating circular refcount dependencies. */ +- if (!(device->cursor_texture = wined3d_device_create_cursor_texture(device, cursor_image))) +- { +- ERR("Failed to create cursor texture.\n"); +- return WINED3DERR_INVALIDCALL; +- } ++ device->cursorWidth = cursor_image->resource.width; ++ device->cursorHeight = cursor_image->resource.height; + + device->cursorWidth = cursor_image->resource.width; + device->cursorHeight = cursor_image->resource.height; +@@ -4193,10 +4123,6 @@ BOOL CDECL wined3d_device_show_cursor(struct wined3d_device *device, BOOL show) + else + SetCursor(NULL); + } +- else if (device->cursor_texture) +- { +- device->bCursorVisible = show; +- } + + return oldVisible; + } +@@ -4353,11 +4279,6 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device, + wined3d_texture_decref(device->logo_texture); + device->logo_texture = NULL; + } +- if (device->cursor_texture) +- { +- wined3d_texture_decref(device->cursor_texture); +- device->cursor_texture = NULL; +- } + } + + if (device->state.fb.render_targets) +diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c +index 7ebdd1b..0a7b68d 100644 +--- a/dlls/wined3d/swapchain.c ++++ b/dlls/wined3d/swapchain.c +@@ -449,27 +449,6 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT + NULL, WINED3D_TEXF_POINT); + } + +- 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, +- }; +- +- TRACE("Rendering the software cursor.\n"); +- +- if (swapchain->desc.windowed) +- MapWindowPoints(NULL, swapchain->win_handle, (POINT *)&destRect, 2); +- wined3d_surface_blt(back_buffer, &destRect, cursor, NULL, WINEDDBLT_ALPHATEST, +- NULL, WINED3D_TEXF_POINT); +- } +- + TRACE("Presenting HDC %p.\n", context->hdc); + + render_to_fbo = swapchain->render_to_fbo; +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 6382375..2f8cab4 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2037,7 +2037,6 @@ struct wined3d_device + UINT xScreenSpace; + UINT yScreenSpace; + UINT cursorWidth, cursorHeight; +- struct wined3d_texture *cursor_texture; + HCURSOR hardwareCursor; + + /* The Wine logo texture */ +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0145-wined3d-Create-dummy-textures-through-the-CS.patch b/patches/wined3d-CSMT_Main/0145-wined3d-Create-dummy-textures-through-the-CS.patch new file mode 100644 index 00000000..8fb0fd38 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0145-wined3d-Create-dummy-textures-through-the-CS.patch @@ -0,0 +1,157 @@ +From c91b5281332e1879e25088efeee24bc1a337ca30 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 10 Oct 2013 16:29:42 +0200 +Subject: wined3d: Create dummy textures through the CS. + +Hacky version. Just good enough to see if the double context during init is what makes fglrx +crash. +--- + dlls/wined3d/cs.c | 29 +++++++++++++++++++++++++++++ + dlls/wined3d/device.c | 13 ++++--------- + dlls/wined3d/wined3d_private.h | 3 ++- + 3 files changed, 35 insertions(+), 10 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 5e4aa53..fb1d1aa 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -87,6 +87,7 @@ enum wined3d_cs_op + WINED3D_CS_OP_VOLUME_CLEANUP, + WINED3D_CS_OP_SURFACE_CLEANUP, + WINED3D_CS_OP_TEXTURE_CLEANUP, ++ WINED3D_CS_OP_CREATE_DUMMY_TEXTURES, + WINED3D_CS_OP_STOP, + }; + +@@ -512,6 +513,11 @@ struct wined3d_cs_texture_cleanup + struct wined3d_texture *texture; + }; + ++struct wined3d_cs_create_dummy_textures ++{ ++ enum wined3d_cs_op opcode; ++}; ++ + static void wined3d_cs_mt_submit(struct wined3d_cs *cs, size_t size) + { + LONG new_val = (cs->queue.head + size) & (WINED3D_CS_QUEUE_SIZE - 1); +@@ -2473,6 +2479,28 @@ void wined3d_cs_emit_texture_cleanup(struct wined3d_cs *cs, struct wined3d_textu + cs->ops->submit(cs, sizeof(*op)); + } + ++static UINT wined3d_cs_exec_create_dummy_textures(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_create_dummy_textures *op = data; ++ struct wined3d_context *context = context_acquire(cs->device, NULL); ++ ++ device_create_dummy_textures(cs->device, context); ++ ++ context_release(context); ++ return sizeof(*op); ++} ++ ++void wined3d_cs_emit_create_dummy_textures(struct wined3d_cs *cs) ++{ ++ struct wined3d_cs_create_dummy_textures *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_CREATE_DUMMY_TEXTURES; ++ ++ cs->ops->submit(cs, sizeof(*op)); ++ cs->ops->finish(cs); ++} ++ + static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = + { + /* WINED3D_CS_OP_NOP */ wined3d_cs_exec_nop, +@@ -2538,6 +2566,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* 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, + }; + + static inline void *_wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size, BOOL prio) +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index b3f75ba..28b1c81 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -608,7 +608,7 @@ out: + } + + /* Context activation is done by the caller. */ +-static void create_dummy_textures(struct wined3d_device *device, struct wined3d_context *context) ++void device_create_dummy_textures(struct wined3d_device *device, struct wined3d_context *context) + { + const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; + unsigned int i, j, count; +@@ -854,7 +854,6 @@ HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device, + { + static const struct wined3d_color black = {0.0f, 0.0f, 0.0f, 0.0f}; + struct wined3d_swapchain *swapchain = NULL; +- struct wined3d_context *context; + DWORD clear_flags = 0; + HRESULT hr; + +@@ -905,9 +904,7 @@ HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device, + device->swapchains[0] = swapchain; + device_init_swapchain_state(device, swapchain); + +- context = context_acquire(device, NULL); +- +- create_dummy_textures(device, context); ++ wined3d_cs_emit_create_dummy_textures(device->cs); + + device->contexts[0]->last_was_rhw = 0; + +@@ -919,7 +916,7 @@ HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device, + + case ORM_BACKBUFFER: + { +- if (context_get_current()->aux_buffers > 0) ++ if (device->contexts[0]->aux_buffers > 0) + { + TRACE("Using auxiliary buffer for offscreen rendering\n"); + device->offscreenBuffer = GL_AUX0; +@@ -935,8 +932,6 @@ HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device, + + TRACE("All defaults now set up, leaving 3D init.\n"); + +- context_release(context); +- + /* Clear the screen */ + if (swapchain->back_buffers && swapchain->back_buffers[0]) + clear_flags |= WINED3DCLEAR_TARGET; +@@ -4236,7 +4231,7 @@ static HRESULT create_primary_opengl_context(struct wined3d_device *device, stru + + swapchain->context[0] = context; + swapchain->num_contexts = 1; +- create_dummy_textures(device, context); ++ device_create_dummy_textures(device, context); + context_release(context); + + return WINED3D_OK; +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 2f8cab4..a4e1886 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2076,7 +2076,7 @@ struct wined3d_gl_bo *wined3d_device_get_bo(struct wined3d_device *device, UINT + GLenum type_hint, struct wined3d_context *context) DECLSPEC_HIDDEN; + void wined3d_device_release_bo(struct wined3d_device *device, struct wined3d_gl_bo *bo, + const struct wined3d_context *context) DECLSPEC_HIDDEN; +- ++void device_create_dummy_textures(struct wined3d_device *device, struct wined3d_context *context) DECLSPEC_HIDDEN; + + static inline BOOL isStateDirty(const struct wined3d_context *context, DWORD state) + { +@@ -2715,6 +2715,7 @@ void wined3d_cs_emit_buffer_cleanup(struct wined3d_cs *cs, struct wined3d_buffer + void wined3d_cs_emit_volume_cleanup(struct wined3d_cs *cs, struct wined3d_volume *volume) DECLSPEC_HIDDEN; + void wined3d_cs_emit_surface_cleanup(struct wined3d_cs *cs, struct wined3d_surface *surface) DECLSPEC_HIDDEN; + void wined3d_cs_emit_texture_cleanup(struct wined3d_cs *cs, struct wined3d_texture *texture) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_create_dummy_textures(struct wined3d_cs *cs) DECLSPEC_HIDDEN; + + /* 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 +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0146-wined3d-Create-the-initial-context-through-the-CS.patch b/patches/wined3d-CSMT_Main/0146-wined3d-Create-the-initial-context-through-the-CS.patch new file mode 100644 index 00000000..2a9fc816 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0146-wined3d-Create-the-initial-context-through-the-CS.patch @@ -0,0 +1,240 @@ +From f53a2f40f946d8e6c9d36de24010dc9d2f324de1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 10 Oct 2013 16:43:19 +0200 +Subject: wined3d: Create the initial context through the CS. + +Very hacky. +--- + dlls/wined3d/cs.c | 34 ++++++++++++ + dlls/wined3d/swapchain.c | 118 +++++++++++++++++++++++------------------ + dlls/wined3d/wined3d_private.h | 4 ++ + 3 files changed, 103 insertions(+), 53 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index fb1d1aa..3662432 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -88,6 +88,7 @@ enum wined3d_cs_op + WINED3D_CS_OP_SURFACE_CLEANUP, + WINED3D_CS_OP_TEXTURE_CLEANUP, + WINED3D_CS_OP_CREATE_DUMMY_TEXTURES, ++ WINED3D_CS_OP_CREATE_SWAPCHAIN_CONTEXT, + WINED3D_CS_OP_STOP, + }; + +@@ -518,6 +519,13 @@ struct wined3d_cs_create_dummy_textures + enum wined3d_cs_op opcode; + }; + ++struct wined3d_cs_create_swapchain_context ++{ ++ enum wined3d_cs_op opcode; ++ struct wined3d_swapchain *swapchain; ++ HRESULT *ret; ++}; ++ + static void wined3d_cs_mt_submit(struct wined3d_cs *cs, size_t size) + { + LONG new_val = (cs->queue.head + size) & (WINED3D_CS_QUEUE_SIZE - 1); +@@ -2501,6 +2509,31 @@ void wined3d_cs_emit_create_dummy_textures(struct wined3d_cs *cs) + cs->ops->finish(cs); + } + ++static UINT wined3d_cs_exec_create_swapchain_context(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_create_swapchain_context *op = data; ++ ++ *op->ret = swapchain_create_context_cs(cs->device, op->swapchain); ++ ++ return sizeof(*op); ++} ++ ++HRESULT wined3d_cs_emit_create_swapchain_context(struct wined3d_cs *cs, struct wined3d_swapchain *swapchain) ++{ ++ HRESULT ret; ++ struct wined3d_cs_create_swapchain_context *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_CREATE_SWAPCHAIN_CONTEXT; ++ op->swapchain = swapchain; ++ op->ret = &ret; ++ ++ cs->ops->submit(cs, sizeof(*op)); ++ cs->ops->finish(cs); ++ ++ return ret; ++} ++ + static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = + { + /* WINED3D_CS_OP_NOP */ wined3d_cs_exec_nop, +@@ -2567,6 +2600,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* 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, + }; + + static inline void *_wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size, BOOL prio) +diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c +index 0a7b68d..8b9b13c 100644 +--- a/dlls/wined3d/swapchain.c ++++ b/dlls/wined3d/swapchain.c +@@ -723,6 +723,69 @@ void swapchain_update_render_to_fbo(struct wined3d_swapchain *swapchain) + swapchain->render_to_fbo = TRUE; + } + ++HRESULT swapchain_create_context_cs(struct wined3d_device *device, struct wined3d_swapchain *swapchain) ++{ ++ const struct wined3d_adapter *adapter = device->adapter; ++ unsigned int i; ++ 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 ++ }; ++ struct wined3d_surface *front_buffer; ++ 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"); ++ return E_OUTOFMEMORY; ++ } ++ 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. */ ++ front_buffer = surface_from_resource(wined3d_texture_get_sub_resource(swapchain->front_buffer, 0)); ++ 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"); ++ HeapFree(GetProcessHeap(), 0, swapchain->context); ++ swapchain->context = NULL; ++ return WINED3DERR_NOTAVAILABLE; ++ } ++ ++ if (wined3d_settings.offscreen_rendering_mode != ORM_FBO ++ && (!swapchain->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]); ++ ++ return WINED3D_OK; ++} ++ + 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) + { +@@ -847,60 +910,9 @@ static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3 + + if (!(device->wined3d->flags & WINED3D_NO3D)) + { +- 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; ++ hr = wined3d_cs_emit_create_swapchain_context(device->cs, swapchain); ++ if (FAILED(hr)) + 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]); + } + + if (swapchain->desc.backbuffer_count > 0) +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index a4e1886..ab38f0e 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2716,6 +2716,8 @@ void wined3d_cs_emit_volume_cleanup(struct wined3d_cs *cs, struct wined3d_volume + void wined3d_cs_emit_surface_cleanup(struct wined3d_cs *cs, struct wined3d_surface *surface) DECLSPEC_HIDDEN; + void wined3d_cs_emit_texture_cleanup(struct wined3d_cs *cs, struct wined3d_texture *texture) DECLSPEC_HIDDEN; + void wined3d_cs_emit_create_dummy_textures(struct wined3d_cs *cs) DECLSPEC_HIDDEN; ++HRESULT wined3d_cs_emit_create_swapchain_context(struct wined3d_cs *cs, ++ struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; + + /* 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 +@@ -2900,6 +2902,8 @@ void swapchain_destroy_contexts(struct wined3d_swapchain *swapchain) DECLSPEC_HI + HDC swapchain_get_backup_dc(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; + void swapchain_update_draw_bindings(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; + void swapchain_update_render_to_fbo(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; ++HRESULT swapchain_create_context_cs(struct wined3d_device *device, ++ struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; + + /***************************************************************************** + * Utility function prototypes +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0147-wined3d-Recreate-ctx-and-dummy-textures-through-the-.patch b/patches/wined3d-CSMT_Main/0147-wined3d-Recreate-ctx-and-dummy-textures-through-the-.patch new file mode 100644 index 00000000..a8bcf440 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0147-wined3d-Recreate-ctx-and-dummy-textures-through-the-.patch @@ -0,0 +1,62 @@ +From bc64eef6fb48de707d8d19cb604e748e207742e4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 10 Oct 2013 18:40:04 +0200 +Subject: wined3d: Recreate ctx and dummy textures through the CS after resets. + +--- + dlls/wined3d/device.c | 26 ++++---------------------- + 1 file changed, 4 insertions(+), 22 deletions(-) + +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index 28b1c81..a113e21 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -4189,8 +4189,6 @@ static void delete_opengl_contexts(struct wined3d_device *device, struct wined3d + + static HRESULT create_primary_opengl_context(struct wined3d_device *device, struct wined3d_swapchain *swapchain) + { +- struct wined3d_context *context; +- struct wined3d_surface *target; + HRESULT hr; + + if (FAILED(hr = device->shader_backend->shader_alloc_private(device, +@@ -4207,32 +4205,16 @@ static HRESULT create_primary_opengl_context(struct wined3d_device *device, stru + return hr; + } + +- /* Recreate the primary swapchain's context */ +- swapchain->context = HeapAlloc(GetProcessHeap(), 0, sizeof(*swapchain->context)); +- if (!swapchain->context) +- { +- ERR("Failed to allocate memory for swapchain context array.\n"); +- device->blitter->free_private(device); +- device->shader_backend->shader_free_private(device); +- return E_OUTOFMEMORY; +- } +- +- target = swapchain->back_buffers +- ? surface_from_resource(wined3d_texture_get_sub_resource(swapchain->back_buffers[0], 0)) +- : surface_from_resource(wined3d_texture_get_sub_resource(swapchain->front_buffer, 0)); +- if (!(context = context_create(swapchain, target, swapchain->ds_format))) ++ hr = wined3d_cs_emit_create_swapchain_context(device->cs, swapchain); ++ if (FAILED(hr)) + { + WARN("Failed to create context.\n"); + device->blitter->free_private(device); + device->shader_backend->shader_free_private(device); +- HeapFree(GetProcessHeap(), 0, swapchain->context); +- return E_FAIL; ++ return hr; + } + +- swapchain->context[0] = context; +- swapchain->num_contexts = 1; +- device_create_dummy_textures(device, context); +- context_release(context); ++ wined3d_cs_emit_create_dummy_textures(device->cs); + + return WINED3D_OK; + } +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0148-wined3d-Ignore-WINED3D_MAP_NO_DIRTY_UPDATE-in-resour.patch b/patches/wined3d-CSMT_Main/0148-wined3d-Ignore-WINED3D_MAP_NO_DIRTY_UPDATE-in-resour.patch new file mode 100644 index 00000000..88b2dd90 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0148-wined3d-Ignore-WINED3D_MAP_NO_DIRTY_UPDATE-in-resour.patch @@ -0,0 +1,37 @@ +From 00632c0c269b313ecf484bf7aff6d61666d27ff9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 10 Oct 2013 19:18:06 +0200 +Subject: wined3d: Ignore WINED3D_MAP_NO_DIRTY_UPDATE in resource_map. + +TODO: This flag and add_dirty_rect need tests. + +The primary purpose of this patch is to fix a memory leak in World of +Warcraft. WoW uses WINED3D_MAP_NO_DIRTY_UPDATE | WINED3D_MAP_DISCARD on +sysmem surfaces. A new block of memory is allocated, but never assigned +to heap_mem because wined3d_cs_emit_resource_changed is not called. + +The bigger picture is that we don't know how this flag and AddDirtyRect +/ AddDirtyBox are supposed to work. Msdn mentions some interaction with +update_surface and update_texture, but personally I think it is more +likely that this functionality is used to update separate rectangles in +a texture, similar to what can be achieved by mapping a buffer twice. +--- + dlls/wined3d/resource.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c +index dd21986..805c6da 100644 +--- a/dlls/wined3d/resource.c ++++ b/dlls/wined3d/resource.c +@@ -849,7 +849,7 @@ HRESULT wined3d_resource_map(struct wined3d_resource *resource, + } + } + +- if (!(flags & (WINED3D_MAP_NO_DIRTY_UPDATE | WINED3D_MAP_READONLY))) ++ if (!(flags & WINED3D_MAP_READONLY)) + resource->unmap_dirtify = TRUE; + + resource->map_count++; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0149-wined3d-Delete-GL-contexts-through-the-CS-in-reset.patch b/patches/wined3d-CSMT_Main/0149-wined3d-Delete-GL-contexts-through-the-CS-in-reset.patch new file mode 100644 index 00000000..845b122b --- /dev/null +++ b/patches/wined3d-CSMT_Main/0149-wined3d-Delete-GL-contexts-through-the-CS-in-reset.patch @@ -0,0 +1,147 @@ +From 2fa4aafc16726b74a32cfcfae23d68749545114f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Fri, 11 Oct 2013 10:11:13 +0200 +Subject: wined3d: Delete GL contexts through the CS in reset. + +Let's see if this fixes the remaining fglrx crashes... +--- + dlls/wined3d/cs.c | 29 +++++++++++++++++++++++++++++ + dlls/wined3d/device.c | 26 +++++++++++++++----------- + dlls/wined3d/wined3d_private.h | 4 ++++ + 3 files changed, 48 insertions(+), 11 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 3662432..489fad0 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -89,6 +89,7 @@ enum wined3d_cs_op + WINED3D_CS_OP_TEXTURE_CLEANUP, + WINED3D_CS_OP_CREATE_DUMMY_TEXTURES, + WINED3D_CS_OP_CREATE_SWAPCHAIN_CONTEXT, ++ WINED3D_CS_OP_DELETE_GL_CONTEXTS, + WINED3D_CS_OP_STOP, + }; + +@@ -526,6 +527,12 @@ struct wined3d_cs_create_swapchain_context + HRESULT *ret; + }; + ++struct wined3d_cs_delete_gl_contexts ++{ ++ enum wined3d_cs_op opcode; ++ struct wined3d_swapchain *swapchain; ++}; ++ + static void wined3d_cs_mt_submit(struct wined3d_cs *cs, size_t size) + { + LONG new_val = (cs->queue.head + size) & (WINED3D_CS_QUEUE_SIZE - 1); +@@ -2534,6 +2541,27 @@ HRESULT wined3d_cs_emit_create_swapchain_context(struct wined3d_cs *cs, struct w + return ret; + } + ++static UINT wined3d_cs_exec_delete_gl_contexts(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_delete_gl_contexts *op = data; ++ ++ device_delete_opengl_contexts_cs(cs->device, op->swapchain); ++ ++ return sizeof(*op); ++} ++ ++void wined3d_cs_emit_delete_opengl_contexts(struct wined3d_cs *cs, struct wined3d_swapchain *swapchain) ++{ ++ struct wined3d_cs_delete_gl_contexts *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_DELETE_GL_CONTEXTS; ++ op->swapchain = swapchain; ++ ++ cs->ops->submit(cs, sizeof(*op)); ++ cs->ops->finish(cs); ++} ++ + static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = + { + /* WINED3D_CS_OP_NOP */ wined3d_cs_exec_nop, +@@ -2601,6 +2629,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* 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, + }; + + static inline void *_wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size, BOOL prio) +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index a113e21..b96f20f 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -4142,22 +4142,12 @@ void CDECL wined3d_device_evict_managed_resources(struct wined3d_device *device) + } + } + +-static void delete_opengl_contexts(struct wined3d_device *device, struct wined3d_swapchain *swapchain) ++void device_delete_opengl_contexts_cs(struct wined3d_device *device, struct wined3d_swapchain *swapchain) + { +- struct wined3d_resource *resource, *cursor; + const struct wined3d_gl_info *gl_info; + struct wined3d_context *context; + struct wined3d_shader *shader; + +- LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &device->resources, struct wined3d_resource, resource_list_entry) +- { +- TRACE("Unloading resource %p.\n", resource); +- +- wined3d_cs_emit_evict_resource(device->cs, resource); +- } +- if (wined3d_settings.cs_multithreaded) +- device->cs->ops->finish(device->cs); +- + LIST_FOR_EACH_ENTRY(shader, &device->shaders, struct wined3d_shader, shader_list_entry) + { + device->shader_backend->shader_destroy(shader); +@@ -4187,6 +4177,20 @@ static void delete_opengl_contexts(struct wined3d_device *device, struct wined3d + swapchain->context = NULL; + } + ++static void delete_opengl_contexts(struct wined3d_device *device, struct wined3d_swapchain *swapchain) ++{ ++ struct wined3d_resource *resource, *cursor; ++ ++ LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &device->resources, struct wined3d_resource, resource_list_entry) ++ { ++ TRACE("Unloading resource %p.\n", resource); ++ ++ wined3d_cs_emit_evict_resource(device->cs, resource); ++ } ++ ++ wined3d_cs_emit_delete_opengl_contexts(device->cs, swapchain); ++} ++ + static HRESULT create_primary_opengl_context(struct wined3d_device *device, struct wined3d_swapchain *swapchain) + { + HRESULT hr; +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index ab38f0e..2f7dd75 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2077,6 +2077,8 @@ struct wined3d_gl_bo *wined3d_device_get_bo(struct wined3d_device *device, UINT + void wined3d_device_release_bo(struct wined3d_device *device, struct wined3d_gl_bo *bo, + const struct wined3d_context *context) DECLSPEC_HIDDEN; + 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; + + static inline BOOL isStateDirty(const struct wined3d_context *context, DWORD state) + { +@@ -2718,6 +2720,8 @@ void wined3d_cs_emit_texture_cleanup(struct wined3d_cs *cs, struct wined3d_textu + void wined3d_cs_emit_create_dummy_textures(struct wined3d_cs *cs) DECLSPEC_HIDDEN; + HRESULT wined3d_cs_emit_create_swapchain_context(struct wined3d_cs *cs, + struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_delete_opengl_contexts(struct wined3d_cs *cs, ++ struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; + + /* 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 +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0150-wined3d-Delete-GL-contexts-through-the-CS-in-uninit_.patch b/patches/wined3d-CSMT_Main/0150-wined3d-Delete-GL-contexts-through-the-CS-in-uninit_.patch new file mode 100644 index 00000000..c55c649c --- /dev/null +++ b/patches/wined3d-CSMT_Main/0150-wined3d-Delete-GL-contexts-through-the-CS-in-uninit_.patch @@ -0,0 +1,79 @@ +From cdfd2659beba10a60a6535bb489c976b97f28ec5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Fri, 11 Oct 2013 10:17:42 +0200 +Subject: wined3d: Delete GL contexts through the CS in uninit_3d. + +--- + dlls/wined3d/device.c | 27 ++------------------------- + 1 file changed, 2 insertions(+), 25 deletions(-) + +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index b96f20f..278bbdc 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -997,8 +997,6 @@ err_out: + HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device) + { + struct wined3d_resource *resource, *cursor; +- const struct wined3d_gl_info *gl_info; +- struct wined3d_context *context; + struct wined3d_surface *surface; + UINT i; + +@@ -1010,12 +1008,6 @@ HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device) + if (wined3d_settings.cs_multithreaded) + device->cs->ops->finish(device->cs); + +- /* I don't think that the interface guarantees that the device is destroyed from the same thread +- * it was created. Thus make sure a context is active for the glDelete* calls +- */ +- context = context_acquire(device, NULL); +- gl_info = context->gl_info; +- + if (device->logo_texture) + wined3d_texture_decref(device->logo_texture); + +@@ -1045,22 +1037,8 @@ HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device) + TRACE("Unloading resource %p.\n", resource); + wined3d_cs_emit_evict_resource(device->cs, resource); + } +- if (wined3d_settings.cs_multithreaded) +- device->cs->ops->finish(device->cs); +- +- /* Destroy the depth blt resources, they will be invalid after the reset. Also free shader +- * private data, it might contain opengl pointers +- */ +- if (device->depth_blt_texture) +- { +- gl_info->gl_ops.gl.p_glDeleteTextures(1, &device->depth_blt_texture); +- device->depth_blt_texture = 0; +- } + +- /* Destroy the shader backend. Note that this has to happen after all shaders are destroyed. */ +- device->blitter->free_private(device); +- device->shader_backend->shader_free_private(device); +- destroy_dummy_textures(device, gl_info); ++ wined3d_cs_emit_delete_opengl_contexts(device->cs, device->swapchains[0]); + + if (device->back_buffer_view) + { +@@ -1068,8 +1046,6 @@ HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device) + device->back_buffer_view = NULL; + } + +- context_release(context); +- + for (i = 0; i < device->swapchain_count; ++i) + { + TRACE("Releasing the implicit swapchain %u.\n", i); +@@ -4175,6 +4151,7 @@ void device_delete_opengl_contexts_cs(struct wined3d_device *device, struct wine + + HeapFree(GetProcessHeap(), 0, swapchain->context); + swapchain->context = NULL; ++ swapchain->num_contexts = 0; + } + + static void delete_opengl_contexts(struct wined3d_device *device, struct wined3d_swapchain *swapchain) +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0151-wined3d-Invoke-surface_unload-through-the-CS-in-wine.patch b/patches/wined3d-CSMT_Main/0151-wined3d-Invoke-surface_unload-through-the-CS-in-wine.patch new file mode 100644 index 00000000..d4a61b28 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0151-wined3d-Invoke-surface_unload-through-the-CS-in-wine.patch @@ -0,0 +1,31 @@ +From 210ed15c0132830fe2a6b4bf422fdc794982cf9c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Fri, 11 Oct 2013 12:09:37 +0200 +Subject: wined3d: Invoke surface_unload through the CS in + wined3d_surface_update_desc. + +This fixes another case where we use a GL context in the main thread and +crash fglrx in doing so. +--- + dlls/wined3d/texture.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c +index f055d5e..09ac38f 100644 +--- a/dlls/wined3d/texture.c ++++ b/dlls/wined3d/texture.c +@@ -769,7 +769,10 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT + } + + if (device->d3d_initialized) +- texture->resource.resource_ops->resource_unload(&texture->resource); ++ { ++ wined3d_cs_emit_evict_resource(device->cs, &surface->resource); ++ device->cs->ops->finish(device->cs); ++ } + + texture->resource.format = format; + texture->resource.multisample_type = multisample_type; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0152-wined3d-Use-an-event-to-block-the-worker-thread-when.patch b/patches/wined3d-CSMT_Main/0152-wined3d-Use-an-event-to-block-the-worker-thread-when.patch new file mode 100644 index 00000000..cce6a5a9 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0152-wined3d-Use-an-event-to-block-the-worker-thread-when.patch @@ -0,0 +1,177 @@ +From e18809d8ea1a9d47a592c91d3bfb703a5df08ac2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 24 Oct 2013 18:56:13 +0200 +Subject: wined3d: Use an event to block the worker thread when it is idle. + +I could not find a canonical implementation for this. Suggestions are +welcome. + +The main goal was to avoid SetEvent / WaitForSingleObject / ResetEvent +calls at all costs. They go straight to wineserver, bringing it to 25% +CPU time and cutting framerates in half. Hence the extra BOOL to tell +cs_submit when to set the event. + +Finding the correct spin count is tricky. The value I set is high enough +to prevent 3DMark2001 car chase high detail from waiting. This benchmark +maps a lot of in-use managed buffers and thus waits for the CS. But what +the ideal number is depends a lot on the game and CPU. + +A better heuristic is needed. E.g. we could tell the worker thread when +the main thread is waiting for a resource to become idle and avoid +waiting for the event in that case. We may have to use POSIX +synchronization primitives for efficiency. On the other hand, the +current implementation probably still spins way too much for an +application that throttles the framerate to 30 fps by waiting in its own +code. So it is probably only good enough for Microsoft Powerpoint. + +We should also think about blocking the main thread with events if it is +waiting for the worker thread when waiting for resources, the swap +counter or space in the command Stream. This should preserve power when +vsync is turned on. +--- + dlls/wined3d/cs.c | 51 +++++++++++++++++++++++++++++++++++++++--- + dlls/wined3d/wined3d_private.h | 5 +++++ + 2 files changed, 53 insertions(+), 3 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 489fad0..8cbca6c 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -539,6 +539,9 @@ static void wined3d_cs_mt_submit(struct wined3d_cs *cs, size_t size) + /* There is only one thread writing to queue.head, InterlockedExchange + * is used for the memory barrier. */ + InterlockedExchange(&cs->queue.head, new_val); ++ ++ if (InterlockedCompareExchange(&cs->waiting_for_event, FALSE, TRUE)) ++ SetEvent(cs->event); + } + + static void wined3d_cs_mt_submit_prio(struct wined3d_cs *cs, size_t size) +@@ -547,6 +550,9 @@ static void wined3d_cs_mt_submit_prio(struct wined3d_cs *cs, size_t size) + /* There is only one thread writing to queue.head, InterlockedExchange + * is used for the memory barrier. */ + InterlockedExchange(&cs->prio_queue.head, new_val); ++ ++ if (InterlockedCompareExchange(&cs->waiting_for_event, FALSE, TRUE)) ++ SetEvent(cs->event); + } + + static UINT wined3d_cs_exec_nop(struct wined3d_cs *cs, const void *data) +@@ -2826,6 +2832,34 @@ static inline void poll_queries(struct wined3d_cs *cs) + } + } + ++static inline BOOL queue_is_empty(const struct wined3d_cs_queue *queue) ++{ ++ return *((volatile LONG *)&queue->head) == queue->tail; ++} ++ ++static void wined3d_cs_wait_event(struct wined3d_cs *cs) ++{ ++ InterlockedExchange(&cs->waiting_for_event, TRUE); ++ ++ /* The main thread might enqueue a finish command and block on it ++ * after the worker thread decided to enter wined3d_cs_wait_event ++ * and before waiting_for_event was set to TRUE. Check again if ++ * the queues are empty */ ++ if (!queue_is_empty(&cs->prio_queue) || !queue_is_empty(&cs->queue)) ++ { ++ /* The main thread might have signalled the event, or be in the process ++ * of doing so. Wait for the event to reset it. ResetEvent is not good ++ * because the main thread might be beween the waiting_for_event reset ++ * and SignalEvent call. */ ++ if (!InterlockedCompareExchange(&cs->waiting_for_event, FALSE, FALSE)) ++ WaitForSingleObject(cs->event, INFINITE); ++ } ++ else ++ { ++ WaitForSingleObject(cs->event, INFINITE); ++ } ++} ++ + static DWORD WINAPI wined3d_cs_run(void *thread_param) + { + struct wined3d_cs *cs = thread_param; +@@ -2833,6 +2867,7 @@ static DWORD WINAPI wined3d_cs_run(void *thread_param) + LONG tail; + char poll = 0; + struct wined3d_cs_queue *queue; ++ unsigned int spin_count = 0; + + TRACE("Started.\n"); + +@@ -2848,21 +2883,27 @@ static DWORD WINAPI wined3d_cs_run(void *thread_param) + else + poll++; + +- if (*((volatile LONG *)&cs->prio_queue.head) != cs->prio_queue.tail) ++ if (!queue_is_empty(&cs->prio_queue)) + { + queue = &cs->prio_queue; + } +- else if (*((volatile LONG *)&cs->queue.head) != cs->queue.tail) ++ else if (!queue_is_empty(&cs->queue)) + { + queue = &cs->queue; +- if (*((volatile LONG *)&cs->prio_queue.head) != cs->prio_queue.tail) ++ if (!queue_is_empty(&cs->prio_queue)) + queue = &cs->prio_queue; + } + else + { ++ spin_count++; ++ if (spin_count >= WINED3D_CS_SPIN_COUNT && list_empty(&cs->query_poll_list)) ++ wined3d_cs_wait_event(cs); ++ + continue; + } + ++ spin_count = 0; ++ + tail = queue->tail; + opcode = *(const enum wined3d_cs_op *)&queue->data[tail]; + +@@ -2904,6 +2945,8 @@ struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device) + { + cs->ops = &wined3d_cs_mt_ops; + ++ cs->event = CreateEventW(NULL, FALSE, FALSE, NULL); ++ + if (!(cs->thread = CreateThread(NULL, 0, wined3d_cs_run, cs, 0, NULL))) + { + ERR("Failed to create wined3d command stream thread.\n"); +@@ -2934,6 +2977,8 @@ void wined3d_cs_destroy(struct wined3d_cs *cs) + CloseHandle(cs->thread); + if (ret != WAIT_OBJECT_0) + ERR("Wait failed (%#x).\n", ret); ++ if (!CloseHandle(cs->event)) ++ ERR("Closing event failed.\n"); + } + + HeapFree(GetProcessHeap(), 0, cs); +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 2f7dd75..63b67da 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2583,6 +2583,8 @@ struct wined3d_cs_list + }; + + #define WINED3D_CS_QUEUE_SIZE 0x100000 ++#define WINED3D_CS_SPIN_COUNT 10000000 ++ + struct wined3d_cs_queue + { + LONG head, tail; +@@ -2612,6 +2614,9 @@ struct wined3d_cs + + LONG pending_presents; + struct list query_poll_list; ++ ++ HANDLE event; ++ BOOL waiting_for_event; + }; + + struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device) DECLSPEC_HIDDEN; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0153-wined3d-Fence-preload-operations.patch b/patches/wined3d-CSMT_Main/0153-wined3d-Fence-preload-operations.patch new file mode 100644 index 00000000..84ce745b --- /dev/null +++ b/patches/wined3d-CSMT_Main/0153-wined3d-Fence-preload-operations.patch @@ -0,0 +1,89 @@ +From 4a770e26268a89e0f211b42dfdd857f3180bb73e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 24 Oct 2013 22:38:26 +0200 +Subject: wined3d: Fence preload operations. + +Otherwise texture data might get lost, thanks to surface/volume_evict_sysmem: + +1) preload(texture) +2) map(texture) + -> Loads sysmem / sets it with discard map. +3) unmap(texture) + -> enqueues a resource_changed operation +4) preload is executed. + -> Uploads data written in 3. Discards sysmem. Questionable if + DISCARD was passed, but without it, no harm done. + -> texture is only up to date location. +5) resource_changed executed. + -> Discards texture. + +And data is lost. This patch prevents that by stalling the map until the +PreLoad is done. + +What's left open is finding out why anyone (I'm looking at you EVE +online) preloads a texture right before mapping it... +--- + dlls/wined3d/cs.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 8cbca6c..b152a0d 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -2145,6 +2145,8 @@ static UINT wined3d_cs_exec_texture_preload(struct wined3d_cs *cs, const void *d + wined3d_texture_load(texture, context, texture->flags & WINED3D_TEXTURE_IS_SRGB); + context_release(context); + ++ wined3d_resource_dec_fence(&texture->resource); ++ + return sizeof(*op); + } + +@@ -2156,6 +2158,8 @@ void wined3d_cs_emit_texture_preload(struct wined3d_cs *cs, struct wined3d_textu + op->opcode = WINED3D_CS_OP_TEXTURE_PRELOAD; + op->texture = texture; + ++ wined3d_resource_inc_fence(&texture->resource); ++ + cs->ops->submit(cs, sizeof(*op)); + } + +@@ -2168,6 +2172,8 @@ static UINT wined3d_cs_exec_surface_preload(struct wined3d_cs *cs, const void *d + wined3d_texture_preload(op->surface->container); + context_release(context); + ++ wined3d_resource_dec_fence(&op->surface->container->resource); ++ + return sizeof(*op); + } + +@@ -2179,6 +2185,8 @@ void wined3d_cs_emit_surface_preload(struct wined3d_cs *cs, struct wined3d_surfa + op->opcode = WINED3D_CS_OP_SURFACE_PRELOAD; + op->surface = surface; + ++ wined3d_resource_inc_fence(&op->surface->container->resource); ++ + cs->ops->submit(cs, sizeof(*op)); + } + +@@ -2300,6 +2308,8 @@ static UINT wined3d_cs_exec_buffer_preload(struct wined3d_cs *cs, const void *da + buffer_internal_preload(op->buffer, context, NULL); + context_release(context); + ++ wined3d_resource_dec_fence(&op->buffer->resource); ++ + return sizeof(*op); + } + +@@ -2311,6 +2321,8 @@ void wined3d_cs_emit_buffer_preload(struct wined3d_cs *cs, struct wined3d_buffer + op->opcode = WINED3D_CS_OP_BUFFER_PRELOAD; + op->buffer = buffer; + ++ wined3d_resource_inc_fence(&buffer->resource); ++ + cs->ops->submit(cs, sizeof(*op)); + } + +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0154-d3d8-tests-D3DLOCK_NO_DIRTY_UPDATE-on-managed-textur.patch b/patches/wined3d-CSMT_Main/0154-d3d8-tests-D3DLOCK_NO_DIRTY_UPDATE-on-managed-textur.patch new file mode 100644 index 00000000..e41dc2c9 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0154-d3d8-tests-D3DLOCK_NO_DIRTY_UPDATE-on-managed-textur.patch @@ -0,0 +1,26 @@ +From c8083ad9f76ddba995df169c8b2f3486e81bbe02 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Wed, 20 Nov 2013 18:04:50 +0100 +Subject: d3d8/tests: D3DLOCK_NO_DIRTY_UPDATE on managed textures is + temporarily broken. + +--- + dlls/d3d8/tests/visual.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/dlls/d3d8/tests/visual.c b/dlls/d3d8/tests/visual.c +index a8a771e..9535b69 100644 +--- a/dlls/d3d8/tests/visual.c ++++ b/dlls/d3d8/tests/visual.c +@@ -4998,7 +4998,7 @@ static void add_dirty_rect_test(void) + fill_surface(surface_managed, 0x0000ff00, D3DLOCK_NO_DIRTY_UPDATE); + add_dirty_rect_test_draw(device); + color = getPixelColor(device, 320, 240); +- ok(color_match(color, 0x00ff0000, 1), ++ todo_wine ok(color_match(color, 0x00ff0000, 1), + "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); +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0155-d3d9-tests-D3DLOCK_NO_DIRTY_UPDATE-on-managed-textur.patch b/patches/wined3d-CSMT_Main/0155-d3d9-tests-D3DLOCK_NO_DIRTY_UPDATE-on-managed-textur.patch new file mode 100644 index 00000000..4ada496d --- /dev/null +++ b/patches/wined3d-CSMT_Main/0155-d3d9-tests-D3DLOCK_NO_DIRTY_UPDATE-on-managed-textur.patch @@ -0,0 +1,26 @@ +From 1bdcaa3e831f627806a00a07fb92ef28502c4f7a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Wed, 20 Nov 2013 18:06:02 +0100 +Subject: d3d9/tests: D3DLOCK_NO_DIRTY_UPDATE on managed textures is + temporarily broken. + +--- + dlls/d3d9/tests/visual.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c +index d1aa3d4..6b28d14 100644 +--- a/dlls/d3d9/tests/visual.c ++++ b/dlls/d3d9/tests/visual.c +@@ -16457,7 +16457,7 @@ static void add_dirty_rect_test(void) + fill_surface(surface_managed, 0x0000ff00, D3DLOCK_NO_DIRTY_UPDATE); + add_dirty_rect_test_draw(device); + color = getPixelColor(device, 320, 240); +- ok(color_match(color, 0x00ff0000, 1), ++ todo_wine ok(color_match(color, 0x00ff0000, 1), + "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); +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0156-wined3d-Completely-reset-the-state-on-reset.patch b/patches/wined3d-CSMT_Main/0156-wined3d-Completely-reset-the-state-on-reset.patch new file mode 100644 index 00000000..58b53134 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0156-wined3d-Completely-reset-the-state-on-reset.patch @@ -0,0 +1,24 @@ +From eb14a8f5c8dc07cda57b588e11f4b3381a340dcb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Fri, 10 Jan 2014 17:57:03 +0100 +Subject: wined3d: Completely reset the state on reset. + +--- + dlls/wined3d/device.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index 278bbdc..62b0625 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -4531,6 +4531,7 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device, + } + wined3d_cs_emit_reset_state(device->cs); + state_cleanup(&device->state); ++ memset(&device->state, 0, sizeof(device->state)); + + if (device->d3d_initialized) + delete_opengl_contexts(device, swapchain); +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0157-wined3d-Send-getdc-and-releasedc-through-the-command.patch b/patches/wined3d-CSMT_Main/0157-wined3d-Send-getdc-and-releasedc-through-the-command.patch new file mode 100644 index 00000000..904846af --- /dev/null +++ b/patches/wined3d-CSMT_Main/0157-wined3d-Send-getdc-and-releasedc-through-the-command.patch @@ -0,0 +1,274 @@ +From 09b215acf85da6b34638c3454ff3d8e00d29ab07 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Sun, 16 Mar 2014 14:13:42 +0100 +Subject: wined3d: Send getdc and releasedc through the command stream. + +As with the palette patch just a cheap workaround for a context +activation bug I just regret that I didn't describe more verbously +earlier. I forgot what it was about exactly and can't be bothered to +investigate atm. +--- + dlls/wined3d/cs.c | 58 +++++++++++++++++++++++++ + dlls/wined3d/surface.c | 96 +++++++++++++++++++++--------------------- + dlls/wined3d/wined3d_private.h | 4 ++ + 3 files changed, 110 insertions(+), 48 deletions(-) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index b152a0d..44930c1 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -90,6 +90,8 @@ enum wined3d_cs_op + WINED3D_CS_OP_CREATE_DUMMY_TEXTURES, + WINED3D_CS_OP_CREATE_SWAPCHAIN_CONTEXT, + WINED3D_CS_OP_DELETE_GL_CONTEXTS, ++ WINED3D_CS_OP_GETDC, ++ WINED3D_CS_OP_RELEASEDC, + WINED3D_CS_OP_STOP, + }; + +@@ -533,6 +535,18 @@ struct wined3d_cs_delete_gl_contexts + struct wined3d_swapchain *swapchain; + }; + ++struct wined3d_cs_getdc ++{ ++ enum wined3d_cs_op opcode; ++ struct wined3d_surface *surface; ++}; ++ ++struct wined3d_cs_releasedc ++{ ++ enum wined3d_cs_op opcode; ++ struct wined3d_surface *surface; ++}; ++ + static void wined3d_cs_mt_submit(struct wined3d_cs *cs, size_t size) + { + LONG new_val = (cs->queue.head + size) & (WINED3D_CS_QUEUE_SIZE - 1); +@@ -2580,6 +2594,48 @@ void wined3d_cs_emit_delete_opengl_contexts(struct wined3d_cs *cs, struct wined3 + cs->ops->finish(cs); + } + ++static UINT wined3d_cs_exec_getdc(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_getdc *op = data; ++ ++ wined3d_surface_getdc_cs(op->surface); ++ ++ return sizeof(*op); ++} ++ ++void wined3d_cs_emit_getdc(struct wined3d_cs *cs, struct wined3d_surface *surface) ++{ ++ struct wined3d_cs_getdc *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_GETDC; ++ op->surface = surface; ++ ++ cs->ops->submit(cs, sizeof(*op)); ++ cs->ops->finish(cs); ++} ++ ++static UINT wined3d_cs_exec_releasedc(struct wined3d_cs *cs, const void *data) ++{ ++ const struct wined3d_cs_releasedc *op = data; ++ ++ wined3d_surface_releasedc_cs(op->surface); ++ ++ return sizeof(*op); ++} ++ ++void wined3d_cs_emit_releasedc(struct wined3d_cs *cs, struct wined3d_surface *surface) ++{ ++ struct wined3d_cs_releasedc *op; ++ ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_RELEASEDC; ++ op->surface = surface; ++ ++ cs->ops->submit(cs, sizeof(*op)); ++ cs->ops->finish(cs); ++} ++ + static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = + { + /* WINED3D_CS_OP_NOP */ wined3d_cs_exec_nop, +@@ -2648,6 +2704,8 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void + /* 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, + }; + + static inline void *_wined3d_cs_mt_require_space(struct wined3d_cs *cs, size_t size, BOOL prio) +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 3c5489f..1ccbe35 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -2468,48 +2468,23 @@ HRESULT CDECL wined3d_surface_map(struct wined3d_surface *surface, + return wined3d_resource_map(&surface->resource, map_desc, rect ? &box : NULL, flags); + } + +-HRESULT CDECL wined3d_surface_getdc(struct wined3d_surface *surface, HDC *dc) ++void wined3d_surface_getdc_cs(struct wined3d_surface *surface) + { +- HRESULT hr; + struct wined3d_device *device = surface->resource.device; + struct wined3d_context *context = NULL; + +- TRACE("surface %p, dc %p.\n", surface, dc); +- +- if (!(surface->resource.format->flags & WINED3DFMT_FLAG_GETDC)) +- { +- WARN("Cannot use GetDC on a %s surface.\n", debug_d3dformat(surface->resource.format->id)); +- return WINED3DERR_INVALIDCALL; +- } +- +- if (wined3d_settings.cs_multithreaded) +- { +- struct wined3d_device *device = surface->resource.device; +- FIXME("Waiting for cs.\n"); +- wined3d_cs_emit_glfinish(device->cs); +- device->cs->ops->finish(device->cs); +- } +- +- /* Give more detailed info for ddraw. */ +- if (surface->flags & SFLAG_DCINUSE) +- return WINEDDERR_DCALREADYCREATED; +- +- /* Can't GetDC if the surface is locked. */ +- if (surface->resource.map_count) +- return WINED3DERR_INVALIDCALL; +- + if (device->d3d_initialized) + context = context_acquire(surface->resource.device, NULL); + + /* Create a DIB section if there isn't a dc yet. */ + if (!surface->hDC) + { +- hr = surface_create_dib_section(surface); ++ HRESULT hr = surface_create_dib_section(surface); + if (FAILED(hr)) + { + if (context) + context_release(context); +- return WINED3DERR_INVALIDCALL; ++ return; + } + if (!(surface->resource.map_binding == WINED3D_LOCATION_USER_MEMORY + || surface->container->flags & WINED3D_TEXTURE_PIN_SYSMEM +@@ -2522,35 +2497,40 @@ HRESULT CDECL wined3d_surface_getdc(struct wined3d_surface *surface, HDC *dc) + + if (context) + context_release(context); +- +- surface->flags |= SFLAG_DCINUSE; +- surface->resource.map_count++; +- +- *dc = surface->hDC; +- TRACE("Returning dc %p.\n", *dc); +- +- return WINED3D_OK; + } + +-HRESULT CDECL wined3d_surface_releasedc(struct wined3d_surface *surface, HDC dc) ++HRESULT CDECL wined3d_surface_getdc(struct wined3d_surface *surface, HDC *dc) + { +- TRACE("surface %p, dc %p.\n", surface, dc); ++ struct wined3d_device *device = surface->resource.device; + +- if (!(surface->flags & SFLAG_DCINUSE)) +- return WINEDDERR_NODC; ++ TRACE("surface %p, dc %p.\n", surface, dc); + +- if (surface->hDC != dc) ++ if (!(surface->resource.format->flags & WINED3DFMT_FLAG_GETDC)) + { +- WARN("Application tries to release invalid DC %p, surface DC is %p.\n", +- dc, surface->hDC); +- return WINEDDERR_NODC; ++ WARN("Cannot use GetDC on a %s surface.\n", debug_d3dformat(surface->resource.format->id)); ++ return WINED3DERR_INVALIDCALL; + } + +- surface->resource.map_count--; +- surface->flags &= ~SFLAG_DCINUSE; ++ /* Give more detailed info for ddraw. */ ++ if (surface->flags & SFLAG_DCINUSE) ++ return WINEDDERR_DCALREADYCREATED; ++ ++ /* Can't GetDC if the surface is locked. */ ++ if (surface->resource.map_count) ++ return WINED3DERR_INVALIDCALL; ++ ++ surface->flags |= SFLAG_DCINUSE; ++ surface->resource.map_count++; ++ wined3d_cs_emit_getdc(device->cs, surface); ++ *dc = surface->hDC; ++ TRACE("Returning dc %p.\n", *dc); ++ ++ return *dc ? WINED3D_OK : WINED3DERR_INVALIDCALL; ++} + +- if (surface->resource.map_binding == WINED3D_LOCATION_USER_MEMORY +- || (surface->container->flags & WINED3D_TEXTURE_PIN_SYSMEM ++void wined3d_surface_releasedc_cs(struct wined3d_surface *surface) ++{ ++ if (surface->resource.map_binding == WINED3D_LOCATION_USER_MEMORY || (surface->container->flags & WINED3D_TEXTURE_PIN_SYSMEM + && surface->resource.map_binding != WINED3D_LOCATION_DIB)) + { + /* The game Salammbo modifies the surface contents without mapping the surface between +@@ -2571,6 +2551,26 @@ HRESULT CDECL wined3d_surface_releasedc(struct wined3d_surface *surface, HDC dc) + if (context) + context_release(context); + } ++} ++ ++HRESULT CDECL wined3d_surface_releasedc(struct wined3d_surface *surface, HDC dc) ++{ ++ TRACE("surface %p, dc %p.\n", surface, dc); ++ ++ if (!(surface->flags & SFLAG_DCINUSE)) ++ return WINEDDERR_NODC; ++ ++ if (surface->hDC != dc) ++ { ++ WARN("Application tries to release invalid DC %p, surface DC is %p.\n", ++ dc, surface->hDC); ++ return WINEDDERR_NODC; ++ } ++ ++ surface->resource.map_count--; ++ surface->flags &= ~SFLAG_DCINUSE; ++ ++ wined3d_cs_emit_releasedc(surface->resource.device->cs, surface); + + return WINED3D_OK; + } +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 63b67da..3abd0a8 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2458,6 +2458,8 @@ void surface_blt_ugly(struct wined3d_surface *dst_surface, const RECT *dst_rect_ + const WINEDDBLTFX *fx, enum wined3d_texture_filter_type filter) DECLSPEC_HIDDEN; + BOOL surface_check_block_align(struct wined3d_surface *surface, const RECT *rect) DECLSPEC_HIDDEN; + 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; + + 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; +@@ -2727,6 +2729,8 @@ HRESULT wined3d_cs_emit_create_swapchain_context(struct wined3d_cs *cs, + struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; + void wined3d_cs_emit_delete_opengl_contexts(struct wined3d_cs *cs, + struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_getdc(struct wined3d_cs *cs, struct wined3d_surface *surface) DECLSPEC_HIDDEN; ++void wined3d_cs_emit_releasedc(struct wined3d_cs *cs, struct wined3d_surface *surface) DECLSPEC_HIDDEN; + + /* 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 +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0158-wined3d-Set-map_heap_memory-NULL-when-allocating-a-P.patch b/patches/wined3d-CSMT_Main/0158-wined3d-Set-map_heap_memory-NULL-when-allocating-a-P.patch new file mode 100644 index 00000000..337d984d --- /dev/null +++ b/patches/wined3d-CSMT_Main/0158-wined3d-Set-map_heap_memory-NULL-when-allocating-a-P.patch @@ -0,0 +1,31 @@ +From 95b883bf187904f5cdd00dbf360ebd444b455a63 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 5 Jun 2014 13:07:27 +0200 +Subject: wined3d: Set map_heap_memory = NULL when allocating a PBO. + +Otherwise the next unmap will re-assign it with the resource_changed +message. Freeing the actual memory and setting the read pointer to 0 is +the task of the worker thread. + +Wined3d_resource_prepare_bo is only called if the map binding is +LOCATION_BUFFER, and map_heap_memory is only used if the map binding is +LOCATION_SYSMEM. +--- + dlls/wined3d/resource.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c +index 805c6da..8069160 100644 +--- a/dlls/wined3d/resource.c ++++ b/dlls/wined3d/resource.c +@@ -585,6 +585,7 @@ static void wined3d_resource_prepare_bo(struct wined3d_resource *resource, struc + GL_STREAM_DRAW_ARB, GL_PIXEL_UNPACK_BUFFER_ARB, context); + resource->map_buffer = resource->buffer; + TRACE("Created GL buffer %u for resource %p.\n", resource->buffer->name, resource); ++ resource->map_heap_memory = NULL; + } + + BOOL wined3d_resource_prepare_system_memory(struct wined3d_resource *resource) +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0159-wined3d-Wait-only-for-the-buffer-to-be-idle.patch b/patches/wined3d-CSMT_Main/0159-wined3d-Wait-only-for-the-buffer-to-be-idle.patch new file mode 100644 index 00000000..bc93743f --- /dev/null +++ b/patches/wined3d-CSMT_Main/0159-wined3d-Wait-only-for-the-buffer-to-be-idle.patch @@ -0,0 +1,27 @@ +From 82ec316a058cc2e1894fb64eee1249ff663f112e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Fri, 22 Aug 2014 15:52:50 +0200 +Subject: wined3d: Wait only for the buffer to be idle. + +This got lost somewhere during the patch reordering. +--- + dlls/wined3d/buffer.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c +index 15ed760..c0f96e3 100644 +--- a/dlls/wined3d/buffer.c ++++ b/dlls/wined3d/buffer.c +@@ -1051,8 +1051,7 @@ HRESULT CDECL wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UIN + } + else if(!(flags & (WINED3D_MAP_NOOVERWRITE | WINED3D_MAP_READONLY))) + { +- FIXME("waiting for cs, flags 0x%04x.\n", flags); +- device->cs->ops->finish(device->cs); ++ wined3d_resource_wait_fence(&buffer->resource); + } + } + +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0160-wined3d-Add-a-comment-about-worker-thread-lag.patch b/patches/wined3d-CSMT_Main/0160-wined3d-Add-a-comment-about-worker-thread-lag.patch new file mode 100644 index 00000000..1294c645 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0160-wined3d-Add-a-comment-about-worker-thread-lag.patch @@ -0,0 +1,31 @@ +From 7cfd19b8d052ed99f3060d5cab1349ec33e162ad Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Mon, 25 Aug 2014 19:57:42 +0200 +Subject: wined3d: Add a comment about worker thread lag. + +--- + dlls/wined3d/cs.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c +index 44930c1..9b890ae 100644 +--- a/dlls/wined3d/cs.c ++++ b/dlls/wined3d/cs.c +@@ -677,6 +677,14 @@ void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *sw + + cs->ops->submit(cs, sizeof(*op)); + ++ /* D3D10 documentation suggests that Windows allows the game to run ++ * 3 frames ahead of the GPU. Increasing this above 1 causes uneven ++ * animation in some games, most notably StarCraft II. The framerates ++ * don't show this problem. The issue is more noticable with vsync ++ * on, but also happens with vsync off. ++ * ++ * In Counter-Strike: Source a frame difference of 3 causes noticable ++ * input delay that makes the game unplayable. */ + while (pending > 1) + pending = InterlockedCompareExchange(&cs->pending_presents, 0, 0); + } +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0161-wined3d-Remove-the-texture-destroy-glFinish.patch b/patches/wined3d-CSMT_Main/0161-wined3d-Remove-the-texture-destroy-glFinish.patch new file mode 100644 index 00000000..a5c6513c --- /dev/null +++ b/patches/wined3d-CSMT_Main/0161-wined3d-Remove-the-texture-destroy-glFinish.patch @@ -0,0 +1,32 @@ +From c064211d94884f2c131c5496e60f591511c5462d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 28 Aug 2014 15:02:12 +0200 +Subject: wined3d: Remove the texture destroy glFinish. + +This should work now that surface_decref is essentially gone and the +container is never unset. +--- + dlls/wined3d/texture.c | 7 ------- + 1 file changed, 7 deletions(-) + +diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c +index 09ac38f..6f78292 100644 +--- a/dlls/wined3d/texture.c ++++ b/dlls/wined3d/texture.c +@@ -146,13 +146,6 @@ static void wined3d_texture_cleanup(struct wined3d_texture *texture) + + TRACE("texture %p.\n", texture); + +- /* Because sub_resource_cleanup interferes with GL resources */ +- if (wined3d_settings.cs_multithreaded) +- { +- FIXME("Waiting for cs.\n"); +- device->cs->ops->finish(device->cs); +- } +- + for (i = 0; i < sub_count; ++i) + { + struct wined3d_resource *sub_resource = texture->sub_resources[i]; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0162-wined3d-Move-FBO-destruction-into-the-worker-thread.patch b/patches/wined3d-CSMT_Main/0162-wined3d-Move-FBO-destruction-into-the-worker-thread.patch new file mode 100644 index 00000000..1e609431 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0162-wined3d-Move-FBO-destruction-into-the-worker-thread.patch @@ -0,0 +1,40 @@ +From 05b16589d0f658e929eaafb416d4b19bd88bb47d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 28 Aug 2014 16:09:45 +0200 +Subject: wined3d: Move FBO destruction into the worker thread. + +This protects the context array against races. +--- + dlls/wined3d/device.c | 2 -- + dlls/wined3d/resource.c | 2 ++ + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index 62b0625..b5ce2c3 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -4638,8 +4638,6 @@ void device_resource_released(struct wined3d_device *device, struct wined3d_reso + + TRACE("device %p, resource %p, type %s.\n", device, resource, debug_d3dresourcetype(type)); + +- context_resource_released(device, resource, type); +- + switch (type) + { + case WINED3D_RTYPE_SURFACE: +diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c +index 8069160..cd60356 100644 +--- a/dlls/wined3d/resource.c ++++ b/dlls/wined3d/resource.c +@@ -159,6 +159,8 @@ void wined3d_resource_free_bo(struct wined3d_resource *resource) + + void wined3d_resource_cleanup_cs(struct wined3d_resource *resource) + { ++ context_resource_released(resource->device, resource, resource->type); ++ + if (resource->buffer) + wined3d_resource_free_bo(resource); + +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0163-wined3d-Don-t-incref-decref-textures-in-color-depth-.patch b/patches/wined3d-CSMT_Main/0163-wined3d-Don-t-incref-decref-textures-in-color-depth-.patch new file mode 100644 index 00000000..8fac5f40 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0163-wined3d-Don-t-incref-decref-textures-in-color-depth-.patch @@ -0,0 +1,134 @@ +From 54eb3e212afc243fef25a46017ae3d822014f336 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Thu, 28 Aug 2014 16:10:09 +0200 +Subject: wined3d: Don't incref / decref textures in color / depth fill blits. + +See comment in the code. The solution is not particularly nice. A better +approach may be to handle them in ddraw, where we have a permanent view +for the surface. +--- + dlls/wined3d/surface.c | 52 +++++++++++++++++++++++++----------------- + dlls/wined3d/view.c | 20 ---------------- + dlls/wined3d/wined3d_private.h | 1 - + 3 files changed, 31 insertions(+), 42 deletions(-) + +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 1ccbe35..82485f3 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -4124,19 +4124,26 @@ static HRESULT ffp_blit_color_fill(struct wined3d_device *device, struct wined3d + const RECT *dst_rect, const struct wined3d_color *color) + { + const RECT draw_rect = {0, 0, dst_surface->resource.width, dst_surface->resource.height}; +- struct wined3d_rendertarget_view *view; +- struct wined3d_fb_state fb = {&view, NULL}; +- HRESULT hr; +- +- if (FAILED(hr = wined3d_rendertarget_view_create_from_surface(dst_surface, +- NULL, &wined3d_null_parent_ops, &view))) +- { +- ERR("Failed to create rendertarget view, hr %#x.\n", hr); +- return hr; +- } ++ struct wined3d_rendertarget_view view, *view_ptr = &view; ++ struct wined3d_fb_state fb = {&view_ptr, NULL, 1}; ++ struct wined3d_texture *texture = dst_surface->container; ++ ++ /* Can't incref / decref the resource here. This is executed inside the worker ++ * thread. Playing with the refcount here makes the worker thread visible to ++ * the client lib. Problems occur when the worker thread happens to hold the ++ * last reference and the resource destruction callbacks are called from the ++ * wrong thread. */ ++ view.resource = &texture->resource; ++ view.parent = NULL; ++ view.parent_ops = &wined3d_null_parent_ops; ++ view.format = dst_surface->resource.format; ++ view.buffer_offset = 0; ++ view.width = dst_surface->resource.width; ++ view.height = dst_surface->resource.height; ++ view.depth = 1; ++ view.sub_resource_idx = dst_surface->texture_layer * texture->level_count + dst_surface->texture_level; + + device_clear_render_targets(device, 1, &fb, 1, dst_rect, &draw_rect, WINED3DCLEAR_TARGET, color, 0.0f, 0); +- wined3d_rendertarget_view_decref_worker(view); + + return WINED3D_OK; + } +@@ -4145,18 +4152,21 @@ static HRESULT ffp_blit_depth_fill(struct wined3d_device *device, struct wined3d + const RECT *dst_rect, float depth) + { + const RECT draw_rect = {0, 0, dst_surface->resource.width, dst_surface->resource.height}; +- struct wined3d_fb_state fb = {NULL, NULL}; +- HRESULT hr; +- +- if (FAILED(hr = wined3d_rendertarget_view_create_from_surface(dst_surface, +- NULL, &wined3d_null_parent_ops, &fb.depth_stencil))) +- { +- ERR("Failed to create rendertarget view, hr %#x.\n", hr); +- return hr; +- } ++ struct wined3d_rendertarget_view view; ++ struct wined3d_fb_state fb = {NULL, &view}; ++ struct wined3d_texture *texture = dst_surface->container; ++ ++ view.resource = &dst_surface->container->resource; ++ view.parent = NULL; ++ view.parent_ops = &wined3d_null_parent_ops; ++ view.format = dst_surface->resource.format; ++ view.buffer_offset = 0; ++ view.width = dst_surface->resource.width; ++ view.height = dst_surface->resource.height; ++ view.depth = 1; ++ view.sub_resource_idx = dst_surface->texture_layer * texture->level_count + dst_surface->texture_level; + + device_clear_render_targets(device, 0, &fb, 1, dst_rect, &draw_rect, WINED3DCLEAR_ZBUFFER, 0, depth, 0); +- wined3d_rendertarget_view_decref_worker(fb.depth_stencil); + + return WINED3D_OK; + } +diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c +index 56eb7b3..870f1df 100644 +--- a/dlls/wined3d/view.c ++++ b/dlls/wined3d/view.c +@@ -58,26 +58,6 @@ ULONG CDECL wined3d_rendertarget_view_decref(struct wined3d_rendertarget_view *v + return refcount; + } + +-/* Ugly hack for ffp_blit_depth_fill that allows destroying a view from inside the +- * worker thread. */ +-ULONG wined3d_rendertarget_view_decref_worker(struct wined3d_rendertarget_view *view) +-{ +- ULONG refcount = InterlockedDecrement(&view->refcount); +- +- TRACE("%p decreasing refcount to %u.\n", view, refcount); +- +- if (!refcount) +- { +- /* 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); +- wined3d_rendertarget_view_destroy(view); +- } +- +- return refcount; +-} +- + void * CDECL wined3d_rendertarget_view_get_parent(const struct wined3d_rendertarget_view *view) + { + TRACE("view %p.\n", view); +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 3abd0a8..88329e5 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -2859,7 +2859,6 @@ static inline struct wined3d_surface *wined3d_rendertarget_view_get_surface( + return surface_from_resource(resource); + } + +-ULONG wined3d_rendertarget_view_decref_worker(struct wined3d_rendertarget_view *view) DECLSPEC_HIDDEN; + void wined3d_rendertarget_view_destroy(struct wined3d_rendertarget_view *view) DECLSPEC_HIDDEN; + + struct wined3d_shader_resource_view +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0164-Winex11-complain-about-glfinish.patch b/patches/wined3d-CSMT_Main/0164-Winex11-complain-about-glfinish.patch new file mode 100644 index 00000000..58fb7060 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0164-Winex11-complain-about-glfinish.patch @@ -0,0 +1,32 @@ +From 422cdfa68ac69e3bbbc08a70b13fdc2afc8fd505 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Fri, 29 Aug 2014 12:12:11 +0200 +Subject: Winex11: complain about glfinish + +--- + dlls/winex11.drv/opengl.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c +index 7b8ba82..42a7498 100644 +--- a/dlls/winex11.drv/opengl.c ++++ b/dlls/winex11.drv/opengl.c +@@ -1983,6 +1983,7 @@ static void wglFinish(void) + escape.code = X11DRV_FLUSH_GL_DRAWABLE; + escape.gl_drawable = 0; + ++ ERR("glFinish\n"); + if ((gl = get_gl_drawable( WindowFromDC( ctx->hdc ), 0 ))) + { + switch (gl->type) +@@ -2008,6 +2009,7 @@ static void wglFlush(void) + escape.code = X11DRV_FLUSH_GL_DRAWABLE; + escape.gl_drawable = 0; + ++ ERR("glFlush\n"); + if ((gl = get_gl_drawable( WindowFromDC( ctx->hdc ), 0 ))) + { + switch (gl->type) +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0165-wined3d-Make-sure-the-new-window-is-set-up-before-se.patch b/patches/wined3d-CSMT_Main/0165-wined3d-Make-sure-the-new-window-is-set-up-before-se.patch new file mode 100644 index 00000000..2deac1c1 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0165-wined3d-Make-sure-the-new-window-is-set-up-before-se.patch @@ -0,0 +1,69 @@ +From 08dd8c4b88837bd88c112f831b589d81339cd286 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Fri, 29 Aug 2014 14:46:19 +0200 +Subject: wined3d: Make sure the new window is set up before setting up a + context. + +--- + dlls/wined3d/device.c | 31 +++++++++++++++++++++---------- + 1 file changed, 21 insertions(+), 10 deletions(-) + +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index b5ce2c3..63eb87e 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -4269,6 +4269,27 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device, + } + } + ++ /* Free implicit resources and wait for the command stream before modifying ++ * swapchain parameters. After modifying the swapchain parameters a new GL ++ * context may be acquired by the worker thread. This causes problems in the ++ * d3d8/9 test that passes a hidden window as the new device window. ++ * SetPixelFormat will call SetWindowPos inside the X11 driver, which sends ++ * a message to the window to query the icon. Since the worker thread is ++ * not the thread that created the window and the d3d8 test does not run ++ * an event loop this deadlocks. Set up the window first from the main thread ++ * before calling SetPixelFormat from the worker thread to avoid this. */ ++ if (device->auto_depth_stencil_view) ++ { ++ wined3d_rendertarget_view_decref(device->auto_depth_stencil_view); ++ device->auto_depth_stencil_view = NULL; ++ } ++ if (device->back_buffer_view) ++ { ++ wined3d_rendertarget_view_decref(device->back_buffer_view); ++ device->back_buffer_view = NULL; ++ } ++ device->cs->ops->finish(device->cs); ++ + /* Is it necessary to recreate the gl context? Actually every setting can be changed + * on an existing gl context, so there's no real need for recreation. + * +@@ -4404,11 +4425,6 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device, + } + } + +- if (device->auto_depth_stencil_view) +- { +- wined3d_rendertarget_view_decref(device->auto_depth_stencil_view); +- device->auto_depth_stencil_view = NULL; +- } + if (swapchain->desc.enable_auto_depth_stencil) + { + struct wined3d_resource_desc surface_desc; +@@ -4446,11 +4462,6 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device, + wined3d_device_set_depth_stencil_view(device, device->auto_depth_stencil_view); + } + +- if (device->back_buffer_view) +- { +- wined3d_rendertarget_view_decref(device->back_buffer_view); +- device->back_buffer_view = NULL; +- } + if (swapchain->desc.backbuffer_count && FAILED(hr = wined3d_rendertarget_view_create_from_surface( + surface_from_resource(wined3d_texture_get_sub_resource(swapchain->back_buffers[0], 0)), + NULL, &wined3d_null_parent_ops, &device->back_buffer_view))) +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0166-wined3d-Remove-the-device_reset-CS-sync-fixme.patch b/patches/wined3d-CSMT_Main/0166-wined3d-Remove-the-device_reset-CS-sync-fixme.patch new file mode 100644 index 00000000..c62bf21b --- /dev/null +++ b/patches/wined3d-CSMT_Main/0166-wined3d-Remove-the-device_reset-CS-sync-fixme.patch @@ -0,0 +1,32 @@ +From 0dafdc38e8dd712f59666224ed22ffe91cc72a76 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Fri, 29 Aug 2014 14:46:55 +0200 +Subject: wined3d: Remove the device_reset CS sync fixme. + +--- + dlls/wined3d/device.c | 9 ++------- + 1 file changed, 2 insertions(+), 7 deletions(-) + +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index 63eb87e..7bc6aeb 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -4215,13 +4215,8 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device, + unsigned int i; + + TRACE("device %p, swapchain_desc %p, mode %p, callback %p.\n", device, swapchain_desc, mode, callback); +- +- if (wined3d_settings.cs_multithreaded) +- { +- FIXME("Waiting for cs.\n"); +- wined3d_cs_emit_glfinish(device->cs); +- device->cs->ops->finish(device->cs); +- } ++ wined3d_cs_emit_glfinish(device->cs); ++ device->cs->ops->finish(device->cs); + + if (!(swapchain = wined3d_device_get_swapchain(device, 0))) + { +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0167-wined3d-Put-GL_APPLE_flush_buffer_range-syncing-back.patch b/patches/wined3d-CSMT_Main/0167-wined3d-Put-GL_APPLE_flush_buffer_range-syncing-back.patch new file mode 100644 index 00000000..9b835dd2 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0167-wined3d-Put-GL_APPLE_flush_buffer_range-syncing-back.patch @@ -0,0 +1,52 @@ +From ee64ddd005a7f0677b34b30b37469d587ae6fc76 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Fri, 29 Aug 2014 18:52:22 +0200 +Subject: wined3d: Put GL_APPLE_flush_buffer_range syncing back in place. + +--- + dlls/wined3d/buffer.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c +index c0f96e3..d743f0a 100644 +--- a/dlls/wined3d/buffer.c ++++ b/dlls/wined3d/buffer.c +@@ -673,6 +673,12 @@ static void buffer_direct_upload(struct wined3d_buffer *This, const struct wined + GL_EXTCALL(glBufferDataARB(This->buffer_type_hint, This->resource.size, NULL, GL_STREAM_DRAW_ARB)); + checkGLcall("glBufferDataARB"); + } ++ else if (flags & WINED3D_BUFFER_SYNC && This->flags & WINED3D_BUFFER_APPLESYNC) ++ { ++ /* OSX doesn't do non-blocking asynchonous glBufferSubData like Linux drivers do, so we want to set ++ * GL_BUFFER_FLUSHING_UNMAP_APPLE to GL_FALSE. This means we have to do synchonization ourselves. */ ++ buffer_sync_apple(This, 0, gl_info); ++ } + + while (This->modified_areas) + { +@@ -1035,9 +1041,9 @@ HRESULT CDECL wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UIN + buffer->flags |= WINED3D_BUFFER_DISCARD; + buffer->ignore_discard = TRUE; + } ++ else if (!(flags & WINED3D_MAP_NOOVERWRITE)) ++ buffer->flags |= WINED3D_BUFFER_SYNC; + } +- if (!(flags & (WINED3D_MAP_NOOVERWRITE | WINED3D_MAP_DISCARD))) +- buffer->flags |= WINED3D_BUFFER_SYNC; + } + + if (wined3d_settings.cs_multithreaded && count == 1) +@@ -1052,6 +1058,10 @@ HRESULT CDECL wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UIN + else if(!(flags & (WINED3D_MAP_NOOVERWRITE | WINED3D_MAP_READONLY))) + { + wined3d_resource_wait_fence(&buffer->resource); ++ /* Writing to the (otherwise worker thread controlled) ++ * flags field is OK here since the wait_fence call made ++ * sure the buffer is idle. */ ++ buffer->flags |= WINED3D_BUFFER_SYNC; + } + } + +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0168-wined3d-Wait-for-the-resource-to-be-idle-when-destro.patch b/patches/wined3d-CSMT_Main/0168-wined3d-Wait-for-the-resource-to-be-idle-when-destro.patch new file mode 100644 index 00000000..9a31859f --- /dev/null +++ b/patches/wined3d-CSMT_Main/0168-wined3d-Wait-for-the-resource-to-be-idle-when-destro.patch @@ -0,0 +1,41 @@ +From ba0d7248f185c8d6024f0d92b8c87b2d7153317c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Wed, 3 Sep 2014 20:20:39 +0200 +Subject: wined3d: Wait for the resource to be idle when destroying user memory + surfaces. + +--- + dlls/wined3d/surface.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 82485f3..3557c00 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -84,6 +84,8 @@ void wined3d_surface_cleanup_cs(struct wined3d_surface *surface) + static void surface_cleanup(struct wined3d_surface *surface) + { + struct wined3d_surface *overlay, *cur; ++ struct wined3d_cs *cs = surface->resource.device->cs; ++ BOOL user_mem = surface->resource.map_binding == WINED3D_LOCATION_USER_MEMORY; + + TRACE("surface %p.\n", surface); + +@@ -97,7 +99,13 @@ static void surface_cleanup(struct wined3d_surface *surface) + } + + resource_cleanup(&surface->resource); +- wined3d_cs_emit_surface_cleanup(surface->resource.device->cs, surface); ++ wined3d_cs_emit_surface_cleanup(cs, surface); ++ ++ /* Wait for the CS to finish operations on this surface when user memory was in use. ++ * The application is allowed to free the memory after texture / surface destruction ++ * returns. */ ++ if (user_mem) ++ wined3d_resource_wait_fence(&surface->container->resource); + } + + void wined3d_surface_destroy(struct wined3d_surface *surface) +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0169-wined3d-Don-t-sync-on-redundant-discard-calls.patch b/patches/wined3d-CSMT_Main/0169-wined3d-Don-t-sync-on-redundant-discard-calls.patch new file mode 100644 index 00000000..6c1ec18e --- /dev/null +++ b/patches/wined3d-CSMT_Main/0169-wined3d-Don-t-sync-on-redundant-discard-calls.patch @@ -0,0 +1,25 @@ +From 4e89934c223fd43aab2679042c7c808c8200aa68 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Mon, 8 Sep 2014 14:53:57 +0200 +Subject: wined3d: Don't sync on redundant discard calls. + +--- + dlls/wined3d/buffer.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c +index d743f0a..1081247 100644 +--- a/dlls/wined3d/buffer.c ++++ b/dlls/wined3d/buffer.c +@@ -1055,7 +1055,7 @@ HRESULT CDECL wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UIN + wined3d_resource_allocate_sysmem(&buffer->resource); + wined3d_cs_emit_buffer_swap_mem(device->cs, buffer, buffer->resource.map_heap_memory); + } +- else if(!(flags & (WINED3D_MAP_NOOVERWRITE | WINED3D_MAP_READONLY))) ++ else if(!(flags & (WINED3D_MAP_NOOVERWRITE | WINED3D_MAP_READONLY)) && !buffer->ignore_discard) + { + wined3d_resource_wait_fence(&buffer->resource); + /* Writing to the (otherwise worker thread controlled) +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0170-wined3d-Don-t-discard-new-buffers.patch b/patches/wined3d-CSMT_Main/0170-wined3d-Don-t-discard-new-buffers.patch new file mode 100644 index 00000000..04691ac5 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0170-wined3d-Don-t-discard-new-buffers.patch @@ -0,0 +1,24 @@ +From 6f08171470d477868721be4e6a1f1178856340d4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Mon, 8 Sep 2014 14:57:37 +0200 +Subject: wined3d: Don't discard new buffers. + +--- + dlls/wined3d/buffer.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c +index 1081247..e6e56bb 100644 +--- a/dlls/wined3d/buffer.c ++++ b/dlls/wined3d/buffer.c +@@ -1196,6 +1196,7 @@ static HRESULT buffer_init(struct wined3d_buffer *buffer, struct wined3d_device + return hr; + } + buffer->buffer_type_hint = bind_hint; ++ buffer->ignore_discard = TRUE; + + 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); +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0171-wined3d-Don-t-try-to-sync-VBOs-manually-on-OSX-with-.patch b/patches/wined3d-CSMT_Main/0171-wined3d-Don-t-try-to-sync-VBOs-manually-on-OSX-with-.patch new file mode 100644 index 00000000..f09c471d --- /dev/null +++ b/patches/wined3d-CSMT_Main/0171-wined3d-Don-t-try-to-sync-VBOs-manually-on-OSX-with-.patch @@ -0,0 +1,52 @@ +From 180d8cf49a4f4481b08e373e8c8a75c116094e63 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Mon, 8 Sep 2014 15:09:44 +0200 +Subject: wined3d: Don't try to sync VBOs manually on OSX with CSMT. + +This fixes a performance regression in some games caused by +aaf4849718c3c3a763c460a24a51dd6c6b55524a. + +GL_ARB_sync and GL_APPLE_fence seem to be fairly slow on OSX. Putting the +buffer back into synchonized mode and synchronizing all future uploads +is about twice as fast. This was benchmarked with 3DMark2001. Gunpoint, +another game that depends on synchronized dynamic buffer maps, feels +smoother, although the lack of a benchmark mode makes testing this difficult. + +This assumes that if a game maps a dynamic buffer without NOOVERWRITE or +DISCARD once it will always do so. I have not seen a game yet that mixes +async and sync maps. If the game mixes them, the wined3d-side CS will still +update the buffer asynchronously. Only the worker thread -> GL copy is +synchronized, as it used to be for all buffers in cx13. + +This patch only changes the double-buffered (used for CSMT) codepath. Making +the same change to the glMapBuffer codepath improves 3DMark2001 performance +as well, but the difference is much smaller. I will leave the manual sync +code in place until we have a game that clearly profits from this change. +--- + dlls/wined3d/buffer.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c +index e6e56bb..b33dd5a 100644 +--- a/dlls/wined3d/buffer.c ++++ b/dlls/wined3d/buffer.c +@@ -676,8 +676,14 @@ static void buffer_direct_upload(struct wined3d_buffer *This, const struct wined + else if (flags & WINED3D_BUFFER_SYNC && This->flags & WINED3D_BUFFER_APPLESYNC) + { + /* OSX doesn't do non-blocking asynchonous glBufferSubData like Linux drivers do, so we want to set +- * GL_BUFFER_FLUSHING_UNMAP_APPLE to GL_FALSE. This means we have to do synchonization ourselves. */ +- buffer_sync_apple(This, 0, gl_info); ++ * GL_BUFFER_SERIALIZED_MODIFY_APPLE to GL_FALSE. Unfortunately ARB_sync and APPLE_fence are pretty ++ * slow on OSX. Putting the buffer back into synchronized mode for future maps is a lot faster. ++ * (GeForce 650M, Mavericks). The difference between ARB_sync and normal buffer operation is small ++ * in the glMapBuffer codepath without CSMT. */ ++ glFinish(); ++ 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; + } + + while (This->modified_areas) +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0172-wined3d-Render-target-lock-hack.patch b/patches/wined3d-CSMT_Main/0172-wined3d-Render-target-lock-hack.patch new file mode 100644 index 00000000..4e279dc0 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0172-wined3d-Render-target-lock-hack.patch @@ -0,0 +1,86 @@ +From f23d42ca6a96a3d257fc57dbae8d5ebd3620e4b7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20D=C3=B6singer?= +Date: Tue, 23 Sep 2014 22:18:56 +0200 +Subject: wined3d: Render target lock hack + +--- + dlls/wined3d/resource.c | 17 +++++++++++++++++ + dlls/wined3d/wined3d_main.c | 7 +++++++ + dlls/wined3d/wined3d_private.h | 1 + + 3 files changed, 25 insertions(+) + +diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c +index cd60356..dc36dd5 100644 +--- a/dlls/wined3d/resource.c ++++ b/dlls/wined3d/resource.c +@@ -777,6 +777,17 @@ HRESULT wined3d_resource_map(struct wined3d_resource *resource, + TRACE("resource %p, map_desc %p, box %p, flags %#x.\n", + resource, map_desc, box, flags); + ++ if (resource->usage & WINED3DUSAGE_RENDERTARGET && wined3d_settings.ignore_rt_map) ++ { ++ WARN("Ignoring render target map, only finishing CS.\n"); ++ wined3d_cs_emit_glfinish(device->cs); ++ map_desc->row_pitch = 0; ++ map_desc->slice_pitch = 0; ++ map_desc->data = NULL; ++ device->cs->ops->finish(device->cs); ++ return WINED3D_OK; ++ } ++ + if (resource->map_count) + { + WARN("Volume is already mapped.\n"); +@@ -880,6 +891,12 @@ HRESULT wined3d_resource_unmap(struct wined3d_resource *resource) + struct wined3d_device *device = resource->device; + TRACE("resource %p.\n", resource); + ++ if (resource->usage & WINED3DUSAGE_RENDERTARGET && wined3d_settings.ignore_rt_map) ++ { ++ WARN("Ignoring render target unmap.\n"); ++ return WINED3D_OK; ++ } ++ + if (!resource->map_count) + { + WARN("Trying to unlock an unlocked resource %p.\n", resource); +diff --git a/dlls/wined3d/wined3d_main.c b/dlls/wined3d/wined3d_main.c +index e6dc444..a1e4e6c 100644 +--- a/dlls/wined3d/wined3d_main.c ++++ b/dlls/wined3d/wined3d_main.c +@@ -86,6 +86,7 @@ struct wined3d_settings wined3d_settings = + ~0U, /* No PS shader model limit by default. */ + FALSE, /* 3D support enabled by default. */ + FALSE, /* No multithreaded CS by default. */ ++ FALSE, /* Do not ignore render target maps. */ + }; + + struct wined3d * CDECL wined3d_create(DWORD flags) +@@ -311,6 +312,12 @@ static BOOL wined3d_dll_init(HINSTANCE hInstDLL) + TRACE("Enabling multithreaded command stream.\n"); + wined3d_settings.cs_multithreaded = TRUE; + } ++ if (!get_config_key(hkey, appkey, "ignore_rt_map", buffer, size) ++ && !strcmp(buffer,"enabled")) ++ { ++ TRACE("Ignoring render target maps.\n"); ++ wined3d_settings.ignore_rt_map = TRUE; ++ } + } + + if (appkey) RegCloseKey( appkey ); +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 88329e5..dd06525 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -281,6 +281,7 @@ struct wined3d_settings + unsigned int max_sm_ps; + BOOL no_3d; + BOOL cs_multithreaded; ++ BOOL ignore_rt_map; + }; + + extern struct wined3d_settings wined3d_settings DECLSPEC_HIDDEN; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0173-wined3d-Avoid-calling-wined3d_surface_blt-from-surfa.patch b/patches/wined3d-CSMT_Main/0173-wined3d-Avoid-calling-wined3d_surface_blt-from-surfa.patch new file mode 100644 index 00000000..f7d57c91 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0173-wined3d-Avoid-calling-wined3d_surface_blt-from-surfa.patch @@ -0,0 +1,42 @@ +From a2aa05486b1b77425b94657483334a1dd5763048 Mon Sep 17 00:00:00 2001 +From: Matteo Bruni +Date: Fri, 12 Sep 2014 19:03:05 +0200 +Subject: wined3d: Avoid calling wined3d_surface_blt() from + surface_upload_from_surface(). + +--- + dlls/wined3d/surface.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 3557c00..9ab0738 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -37,6 +37,10 @@ WINE_DECLARE_DEBUG_CHANNEL(d3d); + #define MAXLOCKCOUNT 50 /* After this amount of locks do not free the sysmem copy. */ + + ++static HRESULT surface_cpu_blt(struct wined3d_surface *dst_surface, const RECT *dst_rect, ++ struct wined3d_surface *src_surface, const RECT *src_rect, DWORD flags, ++ const WINEDDBLTFX *fx, enum wined3d_texture_filter_type filter); ++ + void wined3d_surface_cleanup_cs(struct wined3d_surface *surface) + { + if (surface->rb_multisample || surface->rb_resolved || !list_empty(&surface->renderbuffers)) +@@ -1522,9 +1526,11 @@ HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface, const P + return WINED3DERR_INVALIDCALL; + } + +- /* Use wined3d_surface_blt() instead of uploading directly if we need conversion. */ ++ /* Use surface_cpu_blt() instead of uploading directly if we need ++ * conversion. Avoid calling wined3d_surface_blt() since that goes ++ * through the CS. */ + if (dst_format->convert || wined3d_format_get_color_key_conversion(dst_surface->container, FALSE)) +- return wined3d_surface_blt(dst_surface, &dst_rect, src_surface, src_rect, 0, NULL, WINED3D_TEXF_POINT); ++ return surface_cpu_blt(dst_surface, &dst_rect, src_surface, src_rect, 0, NULL, WINED3D_TEXF_POINT); + + context = context_acquire(dst_surface->resource.device, NULL); + gl_info = context->gl_info; +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0174-wined3d-Fix-some-uninitialized-memory-accesses.patch b/patches/wined3d-CSMT_Main/0174-wined3d-Fix-some-uninitialized-memory-accesses.patch new file mode 100644 index 00000000..7e64953f --- /dev/null +++ b/patches/wined3d-CSMT_Main/0174-wined3d-Fix-some-uninitialized-memory-accesses.patch @@ -0,0 +1,47 @@ +From a8a191d592e1c7202929d272b37afe5a2a347f40 Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Sun, 14 Dec 2014 15:24:44 +0100 +Subject: wined3d: Fix some uninitialized memory accesses. + +--- + dlls/wined3d/device.c | 3 +-- + dlls/wined3d/surface.c | 2 +- + 2 files changed, 2 insertions(+), 3 deletions(-) + +diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c +index 7bc6aeb..50376f7 100644 +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -3370,7 +3370,6 @@ void CDECL wined3d_device_draw_indexed_primitive_instanced(struct wined3d_device + static HRESULT device_update_volume(struct wined3d_context *context, + struct wined3d_volume *src_volume, struct wined3d_volume *dst_volume) + { +- HRESULT hr; + struct wined3d_bo_address data; + + TRACE("src_volume %p, dst_volume %p.\n", +@@ -3395,7 +3394,7 @@ static HRESULT device_update_volume(struct wined3d_context *context, + wined3d_volume_upload_data(dst_volume, context, &data); + wined3d_resource_invalidate_location(&dst_volume->resource, ~WINED3D_LOCATION_TEXTURE_RGB); + +- return hr; ++ return WINED3D_OK; + } + + /* Context activation is done by the caller */ +diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c +index 9ab0738..9a2bcf7 100644 +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -770,7 +770,7 @@ static void surface_blt_fbo(const struct wined3d_device *device, + + if (required_rt && required_rt != old_ctx->current_rt) + { +- restore_rt = context->current_rt; ++ restore_rt = old_ctx->current_rt; + context = context_acquire(device, required_rt); + } + else +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/0175-wined3d-Enable-CSMT-by-default-print-a-winediag-mess.patch b/patches/wined3d-CSMT_Main/0175-wined3d-Enable-CSMT-by-default-print-a-winediag-mess.patch new file mode 100644 index 00000000..3db10da3 --- /dev/null +++ b/patches/wined3d-CSMT_Main/0175-wined3d-Enable-CSMT-by-default-print-a-winediag-mess.patch @@ -0,0 +1,50 @@ +From f5af340900500fbff08b1fb4f3dca8f0c5171d0d Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Sun, 14 Dec 2014 20:15:44 +0100 +Subject: wined3d: Enable CSMT by default, print a winediag message informing + about this patchset. + +--- + dlls/wined3d/wined3d_main.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/dlls/wined3d/wined3d_main.c b/dlls/wined3d/wined3d_main.c +index a1e4e6c..30b1ff5 100644 +--- a/dlls/wined3d/wined3d_main.c ++++ b/dlls/wined3d/wined3d_main.c +@@ -85,7 +85,7 @@ struct wined3d_settings wined3d_settings = + ~0U, /* No GS shader model limit by default. */ + ~0U, /* No PS shader model limit by default. */ + FALSE, /* 3D support enabled by default. */ +- FALSE, /* No multithreaded CS by default. */ ++ TRUE, /* Multithreaded CS by default. */ + FALSE, /* Do not ignore render target maps. */ + }; + +@@ -307,10 +307,10 @@ static BOOL wined3d_dll_init(HINSTANCE hInstDLL) + wined3d_settings.no_3d = TRUE; + } + if (!get_config_key(hkey, appkey, "CSMT", buffer, size) +- && !strcmp(buffer,"enabled")) ++ && !strcmp(buffer,"disabled")) + { +- TRACE("Enabling multithreaded command stream.\n"); +- wined3d_settings.cs_multithreaded = TRUE; ++ TRACE("Disabling multithreaded command stream.\n"); ++ wined3d_settings.cs_multithreaded = FALSE; + } + if (!get_config_key(hkey, appkey, "ignore_rt_map", buffer, size) + && !strcmp(buffer,"enabled")) +@@ -320,6 +320,9 @@ static BOOL wined3d_dll_init(HINSTANCE hInstDLL) + } + } + ++ FIXME_(winediag)("Experimental wined3d CSMT feature is currently %s.\n", ++ wined3d_settings.cs_multithreaded ? "enabled" : "disabled"); ++ + if (appkey) RegCloseKey( appkey ); + if (hkey) RegCloseKey( hkey ); + +-- +2.1.3 + diff --git a/patches/wined3d-CSMT_Main/9999-IfDefined.patch b/patches/wined3d-CSMT_Main/9999-IfDefined.patch new file mode 100644 index 00000000..d2c77c85 --- /dev/null +++ b/patches/wined3d-CSMT_Main/9999-IfDefined.patch @@ -0,0 +1,9662 @@ +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 +@@ -309,7 +309,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, location); ++#endif /* STAGING_CSMT */ + } + + context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, backbuffer, NULL, location); +@@ -417,11 +421,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; +@@ -449,6 +461,29 @@ + 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, ++ }; ++ ++ TRACE("Rendering the software cursor.\n"); ++ ++ if (swapchain->desc.windowed) ++ MapWindowPoints(NULL, swapchain->win_handle, (POINT *)&destRect, 2); ++ wined3d_surface_blt(back_buffer, &destRect, cursor, NULL, WINEDDBLT_ALPHATEST, ++ NULL, WINED3D_TEXF_POINT); ++ } ++ ++#endif /* STAGING_CSMT */ + TRACE("Presenting HDC %p.\n", context->hdc); + + render_to_fbo = swapchain->render_to_fbo; +@@ -490,6 +525,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; +@@ -498,6 +534,16 @@ + else + { + wined3d_resource_load_location(&back_buffer->resource, context, back_buffer->container->resource.draw_binding); ++#else /* STAGING_CSMT */ ++ surface_load_location(back_buffer, 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, back_buffer->container->resource.draw_binding); ++#endif /* STAGING_CSMT */ + } + + if (swapchain->render_to_fbo) +@@ -510,8 +556,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 */ +@@ -534,6 +585,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) +@@ -562,6 +614,61 @@ + { + wined3d_surface_decref(swapchain->device->cs->onscreen_depth_stencil); + swapchain->device->cs->onscreen_depth_stencil = NULL; ++#else /* STAGING_CSMT */ ++ if (!swapchain->render_to_fbo && ((front->locations & WINED3D_LOCATION_SYSMEM) ++ || (back_buffer->locations & WINED3D_LOCATION_SYSMEM))) ++ { ++ /* Both memory copies of the surfaces are ok, flip them around too instead of dirtifying ++ * Doesn't work with render_to_fbo because we're not flipping ++ */ ++ ++ if (front->resource.size == back_buffer->resource.size) ++ { ++ flip_surface(front, back_buffer); ++ ++ /* Tell the front buffer surface that is has been modified. However, ++ * the other locations were preserved during that, so keep the flags. ++ * This serves to update the emulated overlay, if any. */ ++ surface_validate_location(front, WINED3D_LOCATION_DRAWABLE); ++ } ++ else ++ { ++ surface_validate_location(front, WINED3D_LOCATION_DRAWABLE); ++ surface_invalidate_location(front, ~WINED3D_LOCATION_DRAWABLE); ++ surface_validate_location(back_buffer, WINED3D_LOCATION_DRAWABLE); ++ surface_invalidate_location(back_buffer, ~WINED3D_LOCATION_DRAWABLE); ++ } ++ } ++ else ++ { ++ 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. If it is FLIP however, ++ * the texture / sysmem copy needs to be reloaded from the drawable ++ */ ++ if (swapchain->desc.swap_effect == WINED3D_SWAP_EFFECT_FLIP) ++ { ++ surface_validate_location(back_buffer, back_buffer->container->resource.draw_binding); ++ surface_invalidate_location(back_buffer, ~back_buffer->container->resource.draw_binding); ++ } ++ } ++ ++ 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_surface_decref(swapchain->device->onscreen_depth_stencil); ++ swapchain->device->onscreen_depth_stencil = NULL; ++#endif /* STAGING_CSMT */ + } + } + } +@@ -594,7 +701,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, WINED3D_LOCATION_DIB); ++#endif /* STAGING_CSMT */ + + src_dc = front->hDC; + window = swapchain->win_handle; +@@ -622,8 +733,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; + +@@ -650,9 +765,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); +@@ -723,6 +844,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; +@@ -786,6 +908,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) + { +@@ -883,8 +1006,13 @@ + wined3d_texture_set_swapchain(swapchain->front_buffer, swapchain); + 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, +@@ -910,9 +1038,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 +@@ -106,7 +106,11 @@ + static UINT once; + + /* 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; +@@ -381,7 +385,11 @@ + + 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; ++#else /* STAGING_CSMT */ ++ const struct wined3d_format *rt_format = state->fb->render_targets[0]->format; ++#endif /* STAGING_CSMT */ + const struct wined3d_gl_info *gl_info = context->gl_info; + GLenum srcBlend, dstBlend; + enum wined3d_blend d3d_blend; +@@ -826,7 +834,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 +924,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 +942,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); +@@ -1167,10 +1187,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)"); +@@ -1765,7 +1792,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 +@@ -4296,9 +4327,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"); + } + } +@@ -4653,7 +4690,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; + +@@ -4833,7 +4874,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; + +@@ -4900,7 +4945,11 @@ + + void state_srgbwrite(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; ++#else /* STAGING_CSMT */ ++ const struct wined3d_format *rt_format = state->fb->render_targets[0]->format; ++#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 +@@ -4998,7 +4998,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 = 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 +@@ -27,6 +27,21 @@ + WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface); + WINE_DECLARE_DEBUG_CHANNEL(d3d_perf); + ++#if !defined(STAGING_CSMT) ++BOOL volume_prepare_system_memory(struct wined3d_volume *volume) ++{ ++ if (volume->resource.heap_memory) ++ return TRUE; ++ ++ if (!wined3d_resource_allocate_sysmem(&volume->resource)) ++ { ++ ERR("Failed to allocate system memory.\n"); ++ return FALSE; ++ } ++ return TRUE; ++} ++ ++#endif /* STAGING_CSMT */ + /* Context activation is done by the caller. */ + void wined3d_volume_upload_data(struct wined3d_volume *volume, const struct wined3d_context *context, + const struct wined3d_bo_address *data) +@@ -85,6 +100,22 @@ + HeapFree(GetProcessHeap(), 0, mem); + } + ++#if !defined(STAGING_CSMT) ++static 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) +@@ -120,8 +151,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. */ +@@ -163,6 +219,7 @@ + + return TRUE; + } ++#if defined(STAGING_CSMT) + + /* Context activation is done by the caller. */ + static void wined3d_volume_load_location(struct wined3d_resource *resource, +@@ -173,6 +230,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) + { +@@ -191,6 +264,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"); +@@ -220,6 +294,37 @@ + 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_bo_address data = {0, volume->resource.heap_memory}; ++ wined3d_volume_upload_data(volume, context, &data); ++ } ++ else if (volume->locations & WINED3D_LOCATION_BUFFER) ++ { ++ struct wined3d_bo_address data = {volume->pbo, NULL}; ++ 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); +@@ -230,11 +335,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); +@@ -245,6 +363,7 @@ + else + { + FIXME("Implement WINED3D_LOCATION_SYSMEM loading from %s.\n", ++#if defined(STAGING_CSMT) + wined3d_debug_location(volume->resource.locations)); + return; + } +@@ -260,6 +379,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); +@@ -269,6 +410,7 @@ + else + { + FIXME("Implement WINED3D_LOCATION_BUFFER loading from %s.\n", ++#if defined(STAGING_CSMT) + wined3d_debug_location(volume->resource.locations)); + return; + } +@@ -278,6 +420,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 */ + } + } + +@@ -285,6 +438,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); + } +@@ -297,6 +451,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(glGenBuffersARB(1, &volume->pbo)); ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, volume->pbo)); ++ GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, volume->resource.size, NULL, GL_STREAM_DRAW_ARB)); ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 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(glDeleteBuffersARB(1, &volume->pbo)); ++ checkGLcall("glDeleteBuffersARB"); ++ 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) +@@ -310,6 +509,7 @@ + + TRACE("texture %p.\n", resource); + ++#if defined(STAGING_CSMT) + if (wined3d_resource_prepare_system_memory(&volume->resource)) + { + context = context_acquire(device, NULL); +@@ -322,6 +522,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. */ +@@ -337,11 +560,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 */ + ULONG CDECL wined3d_volume_decref(struct wined3d_volume *volume) + { + TRACE("Forwarding to container %p.\n", volume->container); +@@ -368,6 +593,36 @@ + return &volume->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) + { +@@ -393,6 +648,7 @@ + HRESULT CDECL 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; + +@@ -420,6 +676,147 @@ + return hr; + + 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; ++ ++ 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 ((format->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(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 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_ARB, ++ 0, volume->resource.size, mapflags)); ++ } ++ else ++ { ++ GLenum access = wined3d_resource_gl_legacy_map_flags(flags); ++ base_memory = GL_EXTCALL(glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, access)); ++ } ++ ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 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 (format->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_resource_get_pitch(&volume->resource, &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 ((format->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; ++#endif /* STAGING_CSMT */ + } + + struct wined3d_volume * CDECL wined3d_volume_from_resource(struct wined3d_resource *resource) +@@ -429,6 +826,7 @@ + + HRESULT CDECL wined3d_volume_unmap(struct wined3d_volume *volume) + { ++#if defined(STAGING_CSMT) + HRESULT hr; + + if (volume->resource.unmap_dirtify) +@@ -438,6 +836,33 @@ + if (hr == WINEDDERR_NOTLOCKED) + return WINED3DERR_INVALIDCALL; + return hr; ++#else /* STAGING_CSMT */ ++ 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(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, volume->pbo)); ++ GL_EXTCALL(glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB)); ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 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) +@@ -450,6 +875,7 @@ + return wined3d_volume_decref(volume_from_resource(resource)); + } + ++#if defined(STAGING_CSMT) + static void wined3d_volume_location_invalidated(struct wined3d_resource *resource, DWORD location) + { + struct wined3d_volume *volume = volume_from_resource(resource); +@@ -465,6 +891,13 @@ + volume_unload, + wined3d_volume_location_invalidated, + wined3d_volume_load_location, ++#else /* STAGING_CSMT */ ++static const struct wined3d_resource_ops volume_resource_ops = ++{ ++ volume_resource_incref, ++ volume_resource_decref, ++ volume_unload, ++#endif /* STAGING_CSMT */ + }; + + static HRESULT volume_init(struct wined3d_volume *volume, struct wined3d_texture *container, +@@ -501,7 +934,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] +@@ -509,7 +946,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 +@@ -3150,6 +3150,7 @@ + /* case WINED3D_TTFF_COUNT1: Won't ever get here. */ + case WINED3D_TTFF_COUNT2: + mat[2] = mat[6] = mat[10] = mat[14] = 0; ++#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. +@@ -3162,6 +3163,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[3] = mat[7] = mat[11] = 0; mat[15] = 1; + } +@@ -3428,7 +3443,11 @@ + unsigned int i; + DWORD ttff; + DWORD cop, aop, carg0, carg1, carg2, aarg0, aarg1, aarg2; ++#if defined(STAGING_CSMT) + const struct wined3d_format *rt_format = state->fb.render_targets[0]->format; ++#else /* STAGING_CSMT */ ++ const struct wined3d_format *rt_format = state->fb->render_targets[0]->format; ++#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 +@@ -85,8 +85,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) +@@ -306,6 +308,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")) + { +@@ -322,6 +325,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/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 +@@ -706,7 +706,11 @@ + { + const struct wined3d_shader *pshader = state->shader[WINED3D_SHADER_TYPE_PIXEL]; + const struct arb_ps_compiled_shader *gl_shader = priv->compiled_fprog; ++#if defined(STAGING_CSMT) + UINT rt_height = state->fb.render_targets[0]->height; ++#else /* STAGING_CSMT */ ++ UINT rt_height = state->fb->render_targets[0]->height; ++#endif /* STAGING_CSMT */ + + /* Load DirectX 9 float constants for pixel shader */ + priv->highest_dirty_ps_const = shader_arb_load_constantsF(pshader, gl_info, GL_FRAGMENT_PROGRAM_ARB, +@@ -4674,7 +4678,11 @@ + } + else + { ++#if defined(STAGING_CSMT) + UINT rt_height = state->fb.render_targets[0]->height; ++#else /* STAGING_CSMT */ ++ UINT rt_height = state->fb->render_targets[0]->height; ++#endif /* STAGING_CSMT */ + shader_arb_ps_local_constants(compiled, context, state, rt_height); + } + +@@ -7649,7 +7657,11 @@ + + /* Now load the surface */ + if (wined3d_settings.offscreen_rendering_mode != ORM_FBO ++#if defined(STAGING_CSMT) + && (src_surface->resource.locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_DRAWABLE)) ++#else /* STAGING_CSMT */ ++ && (src_surface->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_DRAWABLE)) ++#endif /* STAGING_CSMT */ + == WINED3D_LOCATION_DRAWABLE + && !wined3d_resource_is_offscreen(&src_surface->container->resource)) + { +@@ -7679,6 +7691,7 @@ + /* Leave the opengl state valid for blitting */ + arbfp_blit_unset(context->gl_info); + ++#if defined(STAGING_CSMT) + if (wined3d_settings.cs_multithreaded) + context->gl_info->gl_ops.gl.p_glFinish(); + else if (wined3d_settings.strict_draw_ordering +@@ -7690,6 +7703,17 @@ + + wined3d_resource_validate_location(&dst_surface->resource, dst_surface->container->resource.draw_binding); + wined3d_resource_invalidate_location(&dst_surface->resource, ~dst_surface->container->resource.draw_binding); ++#else /* STAGING_CSMT */ ++ if (wined3d_settings.strict_draw_ordering ++ || (dst_surface->container->swapchain ++ && (dst_surface->container->swapchain->front_buffer == dst_surface->container))) ++ context->gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ ++ ++ context_release(context); ++ ++ surface_validate_location(dst_surface, dst_surface->container->resource.draw_binding); ++ surface_invalidate_location(dst_surface, ~dst_surface->container->resource.draw_binding); ++#endif /* STAGING_CSMT */ + + return WINED3D_OK; + } +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/context.c b/dlls/wined3d/context.c +--- a/dlls/wined3d/context.c ++++ b/dlls/wined3d/context.c +@@ -1448,6 +1448,7 @@ + goto out; + } + ++#if defined(STAGING_CSMT) + ret->current_fb.render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(*ret->current_fb.render_targets) * gl_info->limits.buffers); + ret->current_fb.rt_size = gl_info->limits.buffers; +@@ -1456,6 +1457,7 @@ + if (device->context_count) + ret->offscreenBuffer = device->contexts[0]->offscreenBuffer; + ++#endif /* STAGING_CSMT */ + /* Initialize the texture unit mapping to a 1:1 mapping */ + for (s = 0; s < MAX_COMBINED_SAMPLERS; ++s) + { +@@ -1772,7 +1774,9 @@ + + out: + device->shader_backend->shader_free_context_data(ret); ++#if defined(STAGING_CSMT) + HeapFree(GetProcessHeap(), 0, ret->current_fb.render_targets); ++#endif /* STAGING_CSMT */ + HeapFree(GetProcessHeap(), 0, ret->free_event_queries); + HeapFree(GetProcessHeap(), 0, ret->free_occlusion_queries); + HeapFree(GetProcessHeap(), 0, ret->free_timestamp_queries); +@@ -1806,7 +1810,9 @@ + } + + device->shader_backend->shader_free_context_data(context); ++#if defined(STAGING_CSMT) + HeapFree(GetProcessHeap(), 0, context->current_fb.render_targets); ++#endif /* STAGING_CSMT */ + HeapFree(GetProcessHeap(), 0, context->draw_buffers); + HeapFree(GetProcessHeap(), 0, context->blit_targets); + device_context_remove(device, context); +@@ -2209,7 +2215,11 @@ + return TRUE; + } + ++#if defined(STAGING_CSMT) + /* Context activation is done by the caller. */ ++#else /* STAGING_CSMT */ ++/* The caller provides a context */ ++#endif /* STAGING_CSMT */ + static void context_validate_onscreen_formats(struct wined3d_context *context, + const struct wined3d_rendertarget_view *depth_stencil) + { +@@ -2225,6 +2235,7 @@ + WARN("Depth stencil format is not supported by WGL, rendering the backbuffer in an FBO\n"); + + /* The currently active context is the necessary context to access the swapchain's onscreen buffers */ ++#if defined(STAGING_CSMT) + wined3d_resource_load_location(&context->current_rt->resource, context, WINED3D_LOCATION_TEXTURE_RGB); + swapchain->render_to_fbo = TRUE; + swapchain_update_draw_bindings(swapchain); +@@ -2239,6 +2250,22 @@ + return context_generate_rt_mask_from_surface(rt); + else + return context_generate_rt_mask(context->offscreenBuffer); ++#else /* STAGING_CSMT */ ++ surface_load_location(context->current_rt, WINED3D_LOCATION_TEXTURE_RGB); ++ swapchain->render_to_fbo = TRUE; ++ swapchain_update_draw_bindings(swapchain); ++ context_set_render_offscreen(context, TRUE); ++} ++ ++static DWORD context_generate_rt_mask_no_fbo(const struct wined3d_device *device, const struct wined3d_surface *rt) ++{ ++ if (!rt || rt->resource.format->id == WINED3DFMT_NULL) ++ return 0; ++ else if (rt->container->swapchain) ++ return context_generate_rt_mask_from_surface(rt); ++ else ++ return context_generate_rt_mask(device->offscreenBuffer); ++#endif /* STAGING_CSMT */ + } + + /* Context activation is done by the caller. */ +@@ -2270,7 +2297,11 @@ + } + else + { ++#if defined(STAGING_CSMT) + rt_mask = context_generate_rt_mask_no_fbo(context, rt); ++#else /* STAGING_CSMT */ ++ rt_mask = context_generate_rt_mask_no_fbo(device, rt); ++#endif /* STAGING_CSMT */ + } + + cur_mask = context->current_fbo ? &context->current_fbo->rt_mask : &context->draw_buffers_mask; +@@ -2316,7 +2347,11 @@ + DWORD rt_mask = 0, *cur_mask; + UINT i; + ++#if defined(STAGING_CSMT) + if (isStateDirty(context, STATE_FRAMEBUFFER) || !wined3d_fb_equal(fb, &context->current_fb) ++#else /* STAGING_CSMT */ ++ if (isStateDirty(context, STATE_FRAMEBUFFER) || fb != &device->fb ++#endif /* STAGING_CSMT */ + || rt_count != context->gl_info->limits.buffers) + { + if (!context_validate_rt_config(rt_count, rts, fb->depth_stencil)) +@@ -2356,11 +2391,17 @@ + } + else + { ++#if defined(STAGING_CSMT) + rt_mask = context_generate_rt_mask_no_fbo(context, + rt_count ? wined3d_rendertarget_view_get_surface(rts[0]) : NULL); + } + + wined3d_fb_copy(&context->current_fb, fb); ++#else /* STAGING_CSMT */ ++ rt_mask = context_generate_rt_mask_no_fbo(device, ++ rt_count ? wined3d_rendertarget_view_get_surface(rts[0]) : NULL); ++ } ++#endif /* STAGING_CSMT */ + } + else if (wined3d_settings.offscreen_rendering_mode == ORM_FBO + && (!rt_count || wined3d_resource_is_offscreen(rts[0]->resource))) +@@ -2373,7 +2414,11 @@ + } + else + { ++#if defined(STAGING_CSMT) + rt_mask = context_generate_rt_mask_no_fbo(context, ++#else /* STAGING_CSMT */ ++ rt_mask = context_generate_rt_mask_no_fbo(device, ++#endif /* STAGING_CSMT */ + rt_count ? wined3d_rendertarget_view_get_surface(rts[0]) : NULL); + } + +@@ -2408,6 +2453,7 @@ + return TRUE; + } + ++#if defined(STAGING_CSMT) + static DWORD find_draw_buffers_mask(const struct wined3d_context *context, const struct wined3d_state *state) + { + struct wined3d_rendertarget_view **rts = state->fb.render_targets; +@@ -2417,6 +2463,18 @@ + + if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) + return context_generate_rt_mask_no_fbo(context, wined3d_rendertarget_view_get_surface(rts[0])); ++#else /* STAGING_CSMT */ ++static DWORD find_draw_buffers_mask(const struct wined3d_context *context, const struct wined3d_device *device) ++{ ++ const struct wined3d_state *state = &device->state; ++ struct wined3d_rendertarget_view **rts = state->fb->render_targets; ++ struct wined3d_shader *ps = state->shader[WINED3D_SHADER_TYPE_PIXEL]; ++ DWORD rt_mask, rt_mask_bits; ++ unsigned int i; ++ ++ if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) ++ return context_generate_rt_mask_no_fbo(device, wined3d_rendertarget_view_get_surface(rts[0])); ++#endif /* STAGING_CSMT */ + else if (!context->render_offscreen) + return context_generate_rt_mask_from_surface(wined3d_rendertarget_view_get_surface(rts[0])); + +@@ -2439,8 +2497,14 @@ + /* Context activation is done by the caller. */ + void context_state_fb(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) + { ++#if defined(STAGING_CSMT) + const struct wined3d_fb_state *fb = &state->fb; + DWORD rt_mask = find_draw_buffers_mask(context, state); ++#else /* STAGING_CSMT */ ++ const struct wined3d_device *device = context->swapchain->device; ++ const struct wined3d_fb_state *fb = state->fb; ++ DWORD rt_mask = find_draw_buffers_mask(context, device); ++#endif /* STAGING_CSMT */ + DWORD *cur_mask; + + if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) +@@ -2469,8 +2533,10 @@ + context_apply_draw_buffers(context, rt_mask); + *cur_mask = rt_mask; + } ++#if defined(STAGING_CSMT) + + wined3d_fb_copy(&context->current_fb, &state->fb); ++#endif /* STAGING_CSMT */ + } + + static void context_map_stage(struct wined3d_context *context, DWORD stage, DWORD unit) +@@ -2708,12 +2774,22 @@ + /* Context activation is done by the caller. */ + void context_state_drawbuf(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) + { ++#if defined(STAGING_CSMT) + DWORD rt_mask, *cur_mask; + + if (isStateDirty(context, STATE_FRAMEBUFFER)) return; + + cur_mask = context->current_fbo ? &context->current_fbo->rt_mask : &context->draw_buffers_mask; + rt_mask = find_draw_buffers_mask(context, state); ++#else /* STAGING_CSMT */ ++ const struct wined3d_device *device = context->swapchain->device; ++ DWORD rt_mask, *cur_mask; ++ ++ if (isStateDirty(context, STATE_FRAMEBUFFER)) return; ++ ++ cur_mask = context->current_fbo ? &context->current_fbo->rt_mask : &context->draw_buffers_mask; ++ rt_mask = find_draw_buffers_mask(context, device); ++#endif /* STAGING_CSMT */ + if (rt_mask != *cur_mask) + { + context_apply_draw_buffers(context, rt_mask); +@@ -2895,7 +2971,11 @@ + { + if (state->vertex_declaration->half_float_conv_needed && !stream_info->all_vbo) + { ++#if defined(STAGING_CSMT) + TRACE("Using draw_strided_slow with vertex shaders for FLOAT16 conversion.\n"); ++#else /* STAGING_CSMT */ ++ TRACE("Using drawStridedSlow with vertex shaders for FLOAT16 conversion.\n"); ++#endif /* STAGING_CSMT */ + context->use_immediate_mode_draw = TRUE; + } + else +@@ -2967,11 +3047,19 @@ + } + + /* Context activation is done by the caller. */ ++#if defined(STAGING_CSMT) + BOOL context_apply_draw_state(struct wined3d_context *context, const struct wined3d_device *device, + const struct wined3d_state *state) + { + const struct StateEntry *state_table = context->state_table; + const struct wined3d_fb_state *fb = &state->fb; ++#else /* STAGING_CSMT */ ++BOOL context_apply_draw_state(struct wined3d_context *context, struct wined3d_device *device) ++{ ++ const struct wined3d_state *state = &device->state; ++ const struct StateEntry *state_table = context->state_table; ++ const struct wined3d_fb_state *fb = state->fb; ++#endif /* STAGING_CSMT */ + unsigned int i, j; + WORD map; + +@@ -2998,12 +3086,17 @@ + for (i = 0, map = context->stream_info.use_map; map; map >>= 1, ++i) + { + if (map & 1) ++#if defined(STAGING_CSMT) + buffer_internal_preload(state->streams[context->stream_info.elements[i].stream_idx].buffer, + context, state); + } + /* PreLoad may kick buffers out of vram. */ + if (isStateDirty(context, STATE_STREAMSRC)) + context_update_stream_info(context, state); ++#else /* STAGING_CSMT */ ++ buffer_mark_used(state->streams[context->stream_info.elements[i].stream_idx].buffer); ++ } ++#endif /* STAGING_CSMT */ + } + if (state->index_buffer) + { +@@ -3100,7 +3193,11 @@ + if (texture->texture_srgb.name) + wined3d_texture_load(texture, context, TRUE); + wined3d_texture_load(texture, context, FALSE); ++#if defined(STAGING_CSMT) + wined3d_resource_invalidate_location(&context->current_rt->resource, WINED3D_LOCATION_DRAWABLE); ++#else /* STAGING_CSMT */ ++ surface_invalidate_location(context->current_rt, WINED3D_LOCATION_DRAWABLE); ++#endif /* STAGING_CSMT */ + } + } + +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 ((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_SIZE_ENABLE); ++#endif /* STAGING_CSMT */ + } + + if (stateblock->changed.indices) +@@ -1339,6 +1350,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; + } + +@@ -1356,6 +1368,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++) + { +@@ -1373,6 +1398,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))) + { +@@ -1382,6 +1408,7 @@ + } + state->fb.rt_size = gl_info->limits.buffers; + ++#endif /* STAGING_CSMT */ + if (flags & WINED3D_STATE_INIT_DEFAULT) + state_init_default(state, gl_info); + +@@ -1392,6 +1419,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; + +@@ -1399,6 +1427,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/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c +--- a/dlls/d3d9/tests/visual.c ++++ b/dlls/d3d9/tests/visual.c +@@ -16457,7 +16457,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 +@@ -280,8 +308,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; +@@ -968,9 +998,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 +@@ -1052,8 +1087,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 +@@ -1089,6 +1126,7 @@ + struct list entry; + GLuint id; + struct wined3d_context *context; ++#if defined(STAGING_CSMT) + UINT64 timestamp; + }; + +@@ -1124,6 +1162,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 + { +@@ -1139,7 +1183,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; +@@ -1237,8 +1283,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_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); +@@ -1366,8 +1421,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, +@@ -1916,7 +1975,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]; +@@ -1961,6 +2024,7 @@ + DWORD render_states[WINEHIGHEST_RENDER_STATE + 1]; + }; + ++#if defined(STAGING_CSMT) + struct wined3d_gl_bo + { + GLuint name; +@@ -1969,6 +2033,7 @@ + UINT size; + }; + ++#endif /* STAGING_CSMT */ + #define WINED3D_UNMAPPED_STAGE ~0U + + /* Multithreaded flag. Removed from the public header to signal that +@@ -2024,10 +2089,21 @@ + 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) */ ++#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) */ ++ ++ /* 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; +@@ -2038,6 +2114,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 */ +@@ -2069,6 +2148,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, +@@ -2080,6 +2160,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) + { +@@ -2103,9 +2188,11 @@ + ULONG (*resource_incref)(struct wined3d_resource *resource); + ULONG (*resource_decref)(struct wined3d_resource *resource); + void (*resource_unload)(struct wined3d_resource *resource); ++#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 +@@ -2128,6 +2215,7 @@ + UINT depth; + UINT size; + DWORD priority; ++#if defined(STAGING_CSMT) + void *heap_memory, *map_heap_memory, *user_memory, *bitmap_data; + struct wined3d_gl_bo *buffer, *map_buffer; + UINT custom_row_pitch, custom_slice_pitch; +@@ -2135,6 +2223,11 @@ + DWORD locations; + LONG access_fence; + BOOL unmap_dirtify; ++#else /* STAGING_CSMT */ ++ void *heap_memory; ++ UINT custom_row_pitch, custom_slice_pitch; ++ struct list resource_list_entry; ++#endif /* STAGING_CSMT */ + + void *parent; + const struct wined3d_parent_ops *parent_ops; +@@ -2159,6 +2252,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, +@@ -2205,6 +2299,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 +@@ -2295,7 +2398,9 @@ + void wined3d_texture_apply_state_changes(struct wined3d_texture *texture, + const DWORD samplerStates[WINED3D_HIGHEST_SAMPLER_STATE + 1], + 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, +@@ -2329,9 +2434,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) +@@ -2339,6 +2451,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; +@@ -2351,6 +2464,22 @@ + 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_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; ++void wined3d_volume_upload_data(struct wined3d_volume *volume, const struct wined3d_context *context, ++ const struct wined3d_bo_address *data) DECLSPEC_HIDDEN; ++ ++struct wined3d_surface_dib ++{ ++ HBITMAP DIBsection; ++ void *bitmap_data; ++#endif /* STAGING_CSMT */ + UINT bitmap_size; + }; + +@@ -2376,7 +2505,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 +@@ -2384,12 +2517,25 @@ + 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 pow2Width; ++ UINT pow2Height; ++ ++ /* PBO */ ++ GLuint pbo; ++#endif /* STAGING_CSMT */ + GLuint rb_multisample; + GLuint rb_resolved; + GLenum texture_target; +@@ -2435,10 +2581,19 @@ + 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) DECLSPEC_HIDDEN; ++#else /* STAGING_CSMT */ ++void surface_invalidate_location(struct wined3d_surface *surface, DWORD location) DECLSPEC_HIDDEN; ++void surface_load(struct wined3d_surface *surface, 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) DECLSPEC_HIDDEN; ++HRESULT surface_load_location(struct wined3d_surface *surface, 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 surface_prepare_rb(struct wined3d_surface *surface, + const struct wined3d_gl_info *gl_info, BOOL multisample) DECLSPEC_HIDDEN; +@@ -2450,6 +2605,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; +@@ -2465,6 +2621,18 @@ + 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; + void surface_flip(struct wined3d_surface *front, struct wined3d_surface *back) 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 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; ++void flip_surface(struct wined3d_surface *front, struct wined3d_surface *back) DECLSPEC_HIDDEN; ++#endif /* STAGING_CSMT */ + + /* Surface flags: */ + #define SFLAG_DIBSECTION 0x00000001 /* Has a DIB section attached for GetDC. */ +@@ -2507,8 +2675,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]; +@@ -2576,6 +2746,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; +@@ -2626,6 +2797,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; +@@ -2673,6 +2870,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, +@@ -2732,6 +2930,7 @@ + struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; + void wined3d_cs_emit_getdc(struct wined3d_cs *cs, struct wined3d_surface *surface) DECLSPEC_HIDDEN; + void wined3d_cs_emit_releasedc(struct wined3d_cs *cs, struct wined3d_surface *surface) 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 +@@ -2746,8 +2945,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 +@@ -2761,12 +2964,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 */ +@@ -2793,7 +3000,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; +@@ -2818,11 +3027,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 + { +@@ -2860,8 +3073,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; +@@ -2874,8 +3089,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 +@@ -2915,8 +3134,10 @@ + HDC swapchain_get_backup_dc(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; + void swapchain_update_draw_bindings(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; + void swapchain_update_render_to_fbo(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 +@@ -3135,7 +3356,9 @@ + void shader_generate_main(const struct wined3d_shader *shader, struct wined3d_shader_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 +@@ -48,12 +48,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); +@@ -62,9 +64,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/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c +--- a/dlls/winex11.drv/opengl.c ++++ b/dlls/winex11.drv/opengl.c +@@ -1983,7 +1983,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) +@@ -2009,7 +2011,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; + } + ++#if defined(STAGING_CSMT) + void wined3d_query_destroy(struct wined3d_query *query) + { + /* Queries are specific to the GL context that created them. Not +@@ -263,6 +264,7 @@ + HeapFree(GetProcessHeap(), 0, query); + } + ++#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) + GL_EXTCALL(glGetQueryObjectuivARB(oq->id, GL_QUERY_RESULT_ARB, &samples)); + checkGLcall("glGetQueryObjectuivARB(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(glGetQueryObjectuivARB(oq->id, GL_QUERY_RESULT_ARB, &samples)); ++ checkGLcall("glGetQueryObjectuivARB(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_ARB, ×tamp)); + checkGLcall("glGetQueryObjectuivARB(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_ARB, ×tamp)); ++ checkGLcall("glGetQueryObjectuivARB(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 = {FALSE, 1000 * 1000 * 1000}; ++ ++ 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) +@@ -92,7 +96,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) + { +@@ -100,6 +108,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; +@@ -449,7 +460,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) + { +@@ -506,7 +521,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) + { +@@ -591,10 +610,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; +@@ -607,6 +633,7 @@ + + if (!index_count) return; + ++#if defined(STAGING_CSMT) + context = context_acquire(device, wined3d_rendertarget_view_get_surface(state->fb.render_targets[0])); + if (!context->valid) + { +@@ -648,6 +675,49 @@ + wined3d_cs_switch_onscreen_ds(device->cs, context, ds); + + if (ds->resource.locations & location) ++#else /* STAGING_CSMT */ ++ if (state->render_states[WINED3D_RS_COLORWRITEENABLE]) ++ { ++ /* Invalidate the back buffer memory so LockRect will read it the next time */ ++ for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i) ++ { ++ struct wined3d_surface *target = wined3d_rendertarget_view_get_surface(device->fb.render_targets[i]); ++ if (target) ++ { ++ surface_load_location(target, target->container->resource.draw_binding); ++ surface_invalidate_location(target, ~target->container->resource.draw_binding); ++ } ++ } ++ } ++ ++ context = context_acquire(device, wined3d_rendertarget_view_get_surface(device->fb.render_targets[0])); ++ if (!context->valid) ++ { ++ context_release(context); ++ WARN("Invalid context, skipping draw.\n"); ++ return; ++ } ++ gl_info = context->gl_info; ++ ++ 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; ++ if (state->render_states[WINED3D_RS_ZWRITEENABLE] || state->render_states[WINED3D_RS_ZENABLE]) ++ { ++ struct wined3d_surface *ds = wined3d_rendertarget_view_get_surface(device->fb.depth_stencil); ++ 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); +@@ -660,6 +730,7 @@ + } + } + ++#if defined(STAGING_CSMT) + if (!context_apply_draw_state(context, device, state)) + { + context_release(context); +@@ -670,6 +741,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); +@@ -752,6 +835,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); + } +@@ -770,6 +854,26 @@ + 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 ++ { ++ 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/device.c b/dlls/wined3d/device.c +--- a/dlls/wined3d/device.c ++++ b/dlls/wined3d/device.c +@@ -198,6 +198,24 @@ + device->contexts = new_array; + } + ++#if !defined(STAGING_CSMT) ++void device_switch_onscreen_ds(struct wined3d_device *device, ++ struct wined3d_context *context, struct wined3d_surface *depth_stencil) ++{ ++ if (device->onscreen_depth_stencil) ++ { ++ surface_load_ds_location(device->onscreen_depth_stencil, context, WINED3D_LOCATION_TEXTURE_RGB); ++ ++ surface_modify_ds_location(device->onscreen_depth_stencil, WINED3D_LOCATION_TEXTURE_RGB, ++ device->onscreen_depth_stencil->ds_current_size.cx, ++ device->onscreen_depth_stencil->ds_current_size.cy); ++ wined3d_surface_decref(device->onscreen_depth_stencil); ++ } ++ device->onscreen_depth_stencil = depth_stencil; ++ wined3d_surface_incref(device->onscreen_depth_stencil); ++} ++ ++#endif /* STAGING_CSMT */ + static BOOL is_full_clear(const struct wined3d_surface *target, const RECT *draw_rect, const RECT *clear_rect) + { + /* partial draw rect */ +@@ -220,7 +238,11 @@ + { + RECT current_rect, r; + ++#if defined(STAGING_CSMT) + if (ds->resource.locations & WINED3D_LOCATION_DISCARDED) ++#else /* STAGING_CSMT */ ++ if (ds->locations & WINED3D_LOCATION_DISCARDED) ++#endif /* STAGING_CSMT */ + { + /* Depth buffer was discarded, make it entirely current in its new location since + * there is no other place where we would get data anyway. */ +@@ -228,7 +250,11 @@ + return; + } + ++#if defined(STAGING_CSMT) + if (ds->resource.locations & location) ++#else /* STAGING_CSMT */ ++ if (ds->locations & location) ++#endif /* STAGING_CSMT */ + SetRect(¤t_rect, 0, 0, + ds->ds_current_size.cx, + ds->ds_current_size.cy); +@@ -284,6 +310,7 @@ + unsigned int i; + RECT ds_rect; + ++#if defined(STAGING_CSMT) + context = context_acquire(device, target); + if (!context->valid) + { +@@ -293,6 +320,7 @@ + } + gl_info = context->gl_info; + ++#endif /* STAGING_CSMT */ + /* When we're clearing parts of the drawable, make sure that the target surface is well up to date in the + * drawable. After the clear we'll mark the drawable up to date, so we have to make sure that this is true + * for the cleared parts, and the untouched parts. +@@ -307,9 +335,24 @@ + { + struct wined3d_surface *rt = wined3d_rendertarget_view_get_surface(fb->render_targets[i]); + if (rt) ++#if defined(STAGING_CSMT) + wined3d_resource_load_location(&rt->resource, context, rt->container->resource.draw_binding); + } + } ++#else /* STAGING_CSMT */ ++ surface_load_location(rt, rt->container->resource.draw_binding); ++ } ++ } ++ ++ context = context_acquire(device, target); ++ if (!context->valid) ++ { ++ context_release(context); ++ WARN("Invalid context, skipping clear.\n"); ++ return; ++ } ++ gl_info = context->gl_info; ++#endif /* STAGING_CSMT */ + + if (target) + { +@@ -327,8 +370,13 @@ + { + DWORD location = render_offscreen ? fb->depth_stencil->resource->draw_binding : WINED3D_LOCATION_DRAWABLE; + ++#if defined(STAGING_CSMT) + if (!render_offscreen && depth_stencil != device->cs->onscreen_depth_stencil) + wined3d_cs_switch_onscreen_ds(device->cs, context, depth_stencil); ++#else /* STAGING_CSMT */ ++ if (!render_offscreen && depth_stencil != device->onscreen_depth_stencil) ++ device_switch_onscreen_ds(device, context, depth_stencil); ++#endif /* STAGING_CSMT */ + prepare_ds_clear(depth_stencil, context, location, + draw_rect, rect_count, clear_rect, &ds_rect); + } +@@ -376,8 +424,13 @@ + + if (rt) + { ++#if defined(STAGING_CSMT) + wined3d_resource_validate_location(&rt->resource, rt->container->resource.draw_binding); + wined3d_resource_invalidate_location(&rt->resource, ~rt->container->resource.draw_binding); ++#else /* STAGING_CSMT */ ++ surface_validate_location(rt, rt->container->resource.draw_binding); ++ surface_invalidate_location(rt, ~rt->container->resource.draw_binding); ++#endif /* STAGING_CSMT */ + } + } + +@@ -608,7 +661,11 @@ + } + + /* Context activation is done by the caller. */ ++#if defined(STAGING_CSMT) + void device_create_dummy_textures(struct wined3d_device *device, struct wined3d_context *context) ++#else /* STAGING_CSMT */ ++static void create_dummy_textures(struct wined3d_device *device, struct wined3d_context *context) ++#endif /* STAGING_CSMT */ + { + const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; + unsigned int i, j, count; +@@ -835,7 +892,11 @@ + BOOL ds_enable = !!swapchain->desc.enable_auto_depth_stencil; + unsigned int i; + ++#if defined(STAGING_CSMT) + if (device->state.fb.render_targets) ++#else /* STAGING_CSMT */ ++ if (device->fb.render_targets) ++#endif /* STAGING_CSMT */ + { + for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i) + { +@@ -853,7 +914,13 @@ + struct wined3d_swapchain_desc *swapchain_desc) + { + static const struct wined3d_color black = {0.0f, 0.0f, 0.0f, 0.0f}; ++#if defined(STAGING_CSMT) + struct wined3d_swapchain *swapchain = NULL; ++#else /* STAGING_CSMT */ ++ const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; ++ struct wined3d_swapchain *swapchain = NULL; ++ struct wined3d_context *context; ++#endif /* STAGING_CSMT */ + DWORD clear_flags = 0; + HRESULT hr; + +@@ -864,6 +931,11 @@ + if (device->wined3d->flags & WINED3D_NO3D) + return WINED3DERR_INVALIDCALL; + ++#if !defined(STAGING_CSMT) ++ device->fb.render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ++ sizeof(*device->fb.render_targets) * gl_info->limits.buffers); ++ ++#endif /* STAGING_CSMT */ + if (FAILED(hr = device->shader_backend->shader_alloc_private(device, + device->adapter->vertex_pipe, device->adapter->fragment_pipe))) + { +@@ -904,7 +976,14 @@ + device->swapchains[0] = swapchain; + device_init_swapchain_state(device, swapchain); + ++#if defined(STAGING_CSMT) + wined3d_cs_emit_create_dummy_textures(device->cs); ++#else /* STAGING_CSMT */ ++ context = context_acquire(device, ++ surface_from_resource(wined3d_texture_get_sub_resource(swapchain->front_buffer, 0))); ++ ++ create_dummy_textures(device, context); ++#endif /* STAGING_CSMT */ + + device->contexts[0]->last_was_rhw = 0; + +@@ -916,7 +995,11 @@ + + case ORM_BACKBUFFER: + { ++#if defined(STAGING_CSMT) + if (device->contexts[0]->aux_buffers > 0) ++#else /* STAGING_CSMT */ ++ if (context_get_current()->aux_buffers > 0) ++#endif /* STAGING_CSMT */ + { + TRACE("Using auxiliary buffer for offscreen rendering\n"); + device->offscreenBuffer = GL_AUX0; +@@ -928,9 +1011,16 @@ + } + } + } ++#if defined(STAGING_CSMT) + device->contexts[0]->offscreenBuffer = device->offscreenBuffer; + + TRACE("All defaults now set up, leaving 3D init.\n"); ++#else /* STAGING_CSMT */ ++ ++ TRACE("All defaults now set up, leaving 3D init.\n"); ++ ++ context_release(context); ++#endif /* STAGING_CSMT */ + + /* Clear the screen */ + if (swapchain->back_buffers && swapchain->back_buffers[0]) +@@ -947,6 +1037,9 @@ + return WINED3D_OK; + + err_out: ++#if !defined(STAGING_CSMT) ++ HeapFree(GetProcessHeap(), 0, device->fb.render_targets); ++#endif /* STAGING_CSMT */ + HeapFree(GetProcessHeap(), 0, device->swapchains); + device->swapchain_count = 0; + if (device->back_buffer_view) +@@ -997,6 +1090,10 @@ + HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device) + { + struct wined3d_resource *resource, *cursor; ++#if !defined(STAGING_CSMT) ++ const struct wined3d_gl_info *gl_info; ++ struct wined3d_context *context; ++#endif /* STAGING_CSMT */ + struct wined3d_surface *surface; + UINT i; + +@@ -1005,6 +1102,7 @@ + if (!device->d3d_initialized) + return WINED3DERR_INVALIDCALL; + ++#if defined(STAGING_CSMT) + if (wined3d_settings.cs_multithreaded) + device->cs->ops->finish(device->cs); + +@@ -1045,6 +1143,81 @@ + wined3d_rendertarget_view_decref(device->back_buffer_view); + device->back_buffer_view = NULL; + } ++#else /* STAGING_CSMT */ ++ /* I don't think that the interface guarantees that the device is destroyed from the same thread ++ * it was created. Thus make sure a context is active for the glDelete* calls ++ */ ++ context = context_acquire(device, NULL); ++ gl_info = context->gl_info; ++ ++ if (device->logo_texture) ++ wined3d_texture_decref(device->logo_texture); ++ if (device->cursor_texture) ++ wined3d_texture_decref(device->cursor_texture); ++ ++ state_unbind_resources(&device->state); ++ ++ /* Unload resources */ ++ LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &device->resources, struct wined3d_resource, resource_list_entry) ++ { ++ TRACE("Unloading resource %p.\n", resource); ++ ++ resource->resource_ops->resource_unload(resource); ++ } ++ ++ /* Destroy the depth blt resources, they will be invalid after the reset. Also free shader ++ * private data, it might contain opengl pointers ++ */ ++ if (device->depth_blt_texture) ++ { ++ gl_info->gl_ops.gl.p_glDeleteTextures(1, &device->depth_blt_texture); ++ device->depth_blt_texture = 0; ++ } ++ ++ /* Destroy the shader backend. Note that this has to happen after all shaders are destroyed. */ ++ device->blitter->free_private(device); ++ device->shader_backend->shader_free_private(device); ++ destroy_dummy_textures(device, gl_info); ++ ++ /* Release the buffers (with sanity checks)*/ ++ if (device->onscreen_depth_stencil) ++ { ++ surface = device->onscreen_depth_stencil; ++ device->onscreen_depth_stencil = NULL; ++ wined3d_surface_decref(surface); ++ } ++ ++ if (device->fb.depth_stencil) ++ { ++ struct wined3d_rendertarget_view *view = device->fb.depth_stencil; ++ ++ TRACE("Releasing depth/stencil view %p.\n", view); ++ ++ device->fb.depth_stencil = NULL; ++ wined3d_rendertarget_view_decref(view); ++ } ++ ++ if (device->auto_depth_stencil_view) ++ { ++ struct wined3d_rendertarget_view *view = device->auto_depth_stencil_view; ++ ++ device->auto_depth_stencil_view = NULL; ++ if (wined3d_rendertarget_view_decref(view)) ++ ERR("Something's still holding the auto depth/stencil view (%p).\n", view); ++ } ++ ++ for (i = 0; i < gl_info->limits.buffers; ++i) ++ { ++ wined3d_device_set_rendertarget_view(device, i, NULL, FALSE); ++ } ++ if (device->back_buffer_view) ++ { ++ wined3d_rendertarget_view_decref(device->back_buffer_view); ++ device->back_buffer_view = NULL; ++ } ++ ++ context_release(context); ++#endif /* STAGING_CSMT */ + + for (i = 0; i < device->swapchain_count; ++i) + { +@@ -1057,6 +1230,11 @@ + device->swapchains = NULL; + device->swapchain_count = 0; + ++#if !defined(STAGING_CSMT) ++ HeapFree(GetProcessHeap(), 0, device->fb.render_targets); ++ device->fb.render_targets = NULL; ++ ++#endif /* STAGING_CSMT */ + device->d3d_initialized = FALSE; + + return WINED3D_OK; +@@ -1420,6 +1598,16 @@ + TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", + light->range, light->falloff, light->theta, light->phi); + ++#if !defined(STAGING_CSMT) ++ /* Update the live definitions if the light is currently assigned a glIndex. */ ++ if (object->glIndex != -1 && !device->recording) ++ { ++ if (object->OriginalParms.type != light->type) ++ device_invalidate_state(device, STATE_LIGHT_TYPE); ++ device_invalidate_state(device, STATE_ACTIVELIGHT(object->glIndex)); ++ } ++ ++#endif /* STAGING_CSMT */ + /* Save away the information. */ + object->OriginalParms = *light; + +@@ -1492,9 +1680,11 @@ + FIXME("Unrecognized light type %#x.\n", light->type); + } + ++#if defined(STAGING_CSMT) + if (!device->recording) + wined3d_cs_emit_set_light(device->cs, object); + ++#endif /* STAGING_CSMT */ + return WINED3D_OK; + } + +@@ -1567,6 +1757,14 @@ + { + if (light_info->glIndex != -1) + { ++#if !defined(STAGING_CSMT) ++ if (!device->recording) ++ { ++ device_invalidate_state(device, STATE_LIGHT_TYPE); ++ device_invalidate_state(device, STATE_ACTIVELIGHT(light_info->glIndex)); ++ } ++ ++#endif /* STAGING_CSMT */ + device->update_state->lights[light_info->glIndex] = NULL; + light_info->glIndex = -1; + } +@@ -1608,11 +1806,23 @@ + WARN("Too many concurrently active lights\n"); + return WINED3D_OK; + } ++#if defined(STAGING_CSMT) + } + } + + if (!device->recording) + wined3d_cs_emit_set_light_enable(device->cs, light_idx, enable); ++#else /* STAGING_CSMT */ ++ ++ /* i == light_info->glIndex */ ++ if (!device->recording) ++ { ++ device_invalidate_state(device, STATE_LIGHT_TYPE); ++ device_invalidate_state(device, STATE_ACTIVELIGHT(i)); ++ } ++ } ++ } ++#endif /* STAGING_CSMT */ + + return WINED3D_OK; + } +@@ -1787,9 +1997,11 @@ + TRACE("device %p, base_index %d.\n", device, base_index); + + device->update_state->base_vertex_index = base_index; ++#if defined(STAGING_CSMT) + + if (!device->recording) + wined3d_cs_emit_set_base_vertex_index(device->cs, base_index); ++#endif /* STAGING_CSMT */ + } + + INT CDECL wined3d_device_get_base_vertex_index(const struct wined3d_device *device) +@@ -1834,7 +2046,11 @@ + || !(texture->resource.format->flags & WINED3DFMT_FLAG_DEPTH)) + return; + surface = surface_from_resource(texture->sub_resources[0]); ++#if defined(STAGING_CSMT) + if (!(depth_stencil = wined3d_rendertarget_view_get_surface(state->fb.depth_stencil))) ++#else /* STAGING_CSMT */ ++ if (!(depth_stencil = wined3d_rendertarget_view_get_surface(state->fb->depth_stencil))) ++#endif /* STAGING_CSMT */ + return; + + wined3d_surface_blt(surface, NULL, depth_stencil, NULL, 0, NULL, WINED3D_TEXF_POINT); +@@ -2154,7 +2370,11 @@ + return device->state.sampler[WINED3D_SHADER_TYPE_VERTEX][idx]; + } + ++#if defined(STAGING_CSMT) + void device_invalidate_shader_constants(const struct wined3d_device *device, DWORD mask) ++#else /* STAGING_CSMT */ ++static void device_invalidate_shader_constants(const struct wined3d_device *device, DWORD mask) ++#endif /* STAGING_CSMT */ + { + UINT i; + +@@ -2187,8 +2407,12 @@ + } + else + { ++#if defined(STAGING_CSMT) + wined3d_cs_emit_set_consts_b(device->cs, start_register, constants, + bool_count, WINED3D_SHADER_TYPE_VERTEX); ++#else /* STAGING_CSMT */ ++ device_invalidate_shader_constants(device, WINED3D_SHADER_CONST_VS_B); ++#endif /* STAGING_CSMT */ + } + + return WINED3D_OK; +@@ -2235,8 +2459,12 @@ + } + else + { ++#if defined(STAGING_CSMT) + wined3d_cs_emit_set_consts_i(device->cs, start_register, constants, + vector4i_count, WINED3D_SHADER_TYPE_VERTEX); ++#else /* STAGING_CSMT */ ++ device_invalidate_shader_constants(device, WINED3D_SHADER_CONST_VS_I); ++#endif /* STAGING_CSMT */ + } + + return WINED3D_OK; +@@ -2287,8 +2515,13 @@ + memset(device->recording->changed.vertexShaderConstantsF + start_register, 1, + sizeof(*device->recording->changed.vertexShaderConstantsF) * vector4f_count); + else ++#if defined(STAGING_CSMT) + wined3d_cs_emit_set_consts_f(device->cs, start_register, constants, vector4f_count, + WINED3D_SHADER_TYPE_VERTEX); ++#else /* STAGING_CSMT */ ++ device->shader_backend->shader_update_float_vertex_constants(device, start_register, vector4f_count); ++ ++#endif /* STAGING_CSMT */ + + return WINED3D_OK; + } +@@ -2423,8 +2656,12 @@ + } + else + { ++#if defined(STAGING_CSMT) + wined3d_cs_emit_set_consts_b(device->cs, start_register, constants, + bool_count, WINED3D_SHADER_TYPE_PIXEL); ++#else /* STAGING_CSMT */ ++ device_invalidate_shader_constants(device, WINED3D_SHADER_CONST_PS_B); ++#endif /* STAGING_CSMT */ + } + + return WINED3D_OK; +@@ -2471,8 +2708,12 @@ + } + else + { ++#if defined(STAGING_CSMT) + wined3d_cs_emit_set_consts_i(device->cs, start_register, constants, + vector4i_count, WINED3D_SHADER_TYPE_PIXEL); ++#else /* STAGING_CSMT */ ++ device_invalidate_shader_constants(device, WINED3D_SHADER_CONST_PS_I); ++#endif /* STAGING_CSMT */ + } + + return WINED3D_OK; +@@ -2524,8 +2765,12 @@ + memset(device->recording->changed.pixelShaderConstantsF + start_register, 1, + sizeof(*device->recording->changed.pixelShaderConstantsF) * vector4f_count); + else ++#if defined(STAGING_CSMT) + wined3d_cs_emit_set_consts_f(device->cs, start_register, constants, vector4f_count, + WINED3D_SHADER_TYPE_PIXEL); ++#else /* STAGING_CSMT */ ++ device->shader_backend->shader_update_float_pixel_constants(device, start_register, vector4f_count); ++#endif /* STAGING_CSMT */ + + return WINED3D_OK; + } +@@ -2685,6 +2930,7 @@ + return hr; + } + ++#if defined(STAGING_CSMT) + if (wined3d_settings.cs_multithreaded) + { + FIXME("Waiting for cs.\n"); +@@ -2692,6 +2938,7 @@ + device->cs->ops->finish(device->cs); + } + ++#endif /* STAGING_CSMT */ + wined3d_device_get_transform(device, WINED3D_TS_VIEW, &view_mat); + wined3d_device_get_transform(device, WINED3D_TS_PROJECTION, &proj_mat); + wined3d_device_get_transform(device, WINED3D_TS_WORLD_MATRIX(0), &world_mat); +@@ -3193,6 +3440,10 @@ + + HRESULT CDECL wined3d_device_end_scene(struct wined3d_device *device) + { ++#if !defined(STAGING_CSMT) ++ struct wined3d_context *context; ++ ++#endif /* STAGING_CSMT */ + TRACE("device %p.\n", device); + + if (!device->inScene) +@@ -3201,6 +3452,15 @@ + return WINED3DERR_INVALIDCALL; + } + ++#if !defined(STAGING_CSMT) ++ context = context_acquire(device, NULL); ++ /* We only have to do this if we need to read the, swapbuffers performs a flush for us */ ++ context->gl_info->gl_ops.gl.p_glFlush(); ++ /* No checkGLcall here to avoid locking the lock just for checking a call that hardly ever ++ * fails. */ ++ context_release(context); ++ ++#endif /* STAGING_CSMT */ + device->inScene = FALSE; + return WINED3D_OK; + } +@@ -3226,8 +3486,10 @@ + HRESULT CDECL wined3d_device_clear(struct wined3d_device *device, DWORD rect_count, + const RECT *rects, DWORD flags, const struct wined3d_color *color, float depth, DWORD stencil) + { ++#if defined(STAGING_CSMT) + const struct wined3d_fb_state *fb = &device->state.fb; + ++#endif /* STAGING_CSMT */ + TRACE("device %p, rect_count %u, rects %p, flags %#x, color {%.8e, %.8e, %.8e, %.8e}, depth %.8e, stencil %u.\n", + device, rect_count, rects, flags, color->r, color->g, color->b, color->a, depth, stencil); + +@@ -3236,12 +3498,19 @@ + WARN("Rects is %p, but rect_count is 0, ignoring clear\n", rects); + return WINED3D_OK; + } ++#if defined(STAGING_CSMT) + if (rect_count && !rects) + rect_count = 0; + + if (flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL)) + { + struct wined3d_rendertarget_view *ds = fb->depth_stencil; ++#else /* STAGING_CSMT */ ++ ++ if (flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL)) ++ { ++ struct wined3d_rendertarget_view *ds = device->fb.depth_stencil; ++#endif /* STAGING_CSMT */ + if (!ds) + { + WARN("Clearing depth and/or stencil without a depth stencil buffer attached, returning WINED3DERR_INVALIDCALL\n"); +@@ -3250,8 +3519,13 @@ + } + else if (flags & WINED3DCLEAR_TARGET) + { ++#if defined(STAGING_CSMT) + if (ds->width < fb->render_targets[0]->width + || ds->height < fb->render_targets[0]->height) ++#else /* STAGING_CSMT */ ++ if (ds->width < device->fb.render_targets[0]->width ++ || ds->height < device->fb.render_targets[0]->height) ++#endif /* STAGING_CSMT */ + { + WARN("Silently ignoring depth and target clear with mismatching sizes\n"); + return WINED3D_OK; +@@ -3297,6 +3571,9 @@ + enum wined3d_primitive_type primitive_type) + { + GLenum gl_primitive_type, prev; ++#if !defined(STAGING_CSMT) ++ ++#endif /* STAGING_CSMT */ + TRACE("device %p, primitive_type %s\n", device, debug_d3dprimitivetype(primitive_type)); + + gl_primitive_type = gl_primitive_type_from_d3d(primitive_type); +@@ -3304,8 +3581,13 @@ + device->update_state->gl_primitive_type = gl_primitive_type; + if (device->recording) + device->recording->changed.primitive_type = TRUE; ++#if defined(STAGING_CSMT) + else if (gl_primitive_type != prev) + wined3d_cs_emit_set_primitive_type(device->cs, gl_primitive_type); ++#else /* STAGING_CSMT */ ++ else if (gl_primitive_type != prev && (gl_primitive_type == GL_POINTS || prev == GL_POINTS)) ++ device_invalidate_state(device, STATE_POINT_SIZE_ENABLE); ++#endif /* STAGING_CSMT */ + } + + void CDECL wined3d_device_get_primitive_type(const struct wined3d_device *device, +@@ -3328,6 +3610,14 @@ + return WINED3DERR_INVALIDCALL; + } + ++#if !defined(STAGING_CSMT) ++ if (device->state.load_base_vertex_index) ++ { ++ device->state.load_base_vertex_index = 0; ++ device_invalidate_state(device, STATE_BASEVERTEXINDEX); ++ } ++ ++#endif /* STAGING_CSMT */ + wined3d_cs_emit_draw(device->cs, start_vertex, vertex_count, 0, 0, FALSE); + + return WINED3D_OK; +@@ -3335,6 +3625,10 @@ + + HRESULT CDECL wined3d_device_draw_indexed_primitive(struct wined3d_device *device, UINT start_idx, UINT index_count) + { ++#if !defined(STAGING_CSMT) ++ const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; ++ ++#endif /* STAGING_CSMT */ + TRACE("device %p, start_idx %u, index_count %u.\n", device, start_idx, index_count); + + if (!device->state.index_buffer) +@@ -3353,6 +3647,15 @@ + return WINED3DERR_INVALIDCALL; + } + ++#if !defined(STAGING_CSMT) ++ if (!gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX] && ++ device->state.load_base_vertex_index != device->state.base_vertex_index) ++ { ++ device->state.load_base_vertex_index = device->state.base_vertex_index; ++ device_invalidate_state(device, STATE_BASEVERTEXINDEX); ++ } ++ ++#endif /* STAGING_CSMT */ + wined3d_cs_emit_draw(device->cs, start_idx, index_count, 0, 0, TRUE); + + return WINED3D_OK; +@@ -3367,6 +3670,7 @@ + } + + /* This is a helper function for UpdateTexture, there is no UpdateVolume method in D3D. */ ++#if defined(STAGING_CSMT) + static HRESULT device_update_volume(struct wined3d_context *context, + struct wined3d_volume *src_volume, struct wined3d_volume *dst_volume) + { +@@ -3374,6 +3678,18 @@ + + TRACE("src_volume %p, dst_volume %p.\n", + src_volume, dst_volume); ++#else /* STAGING_CSMT */ ++static HRESULT device_update_volume(struct wined3d_device *device, ++ struct wined3d_volume *src_volume, struct wined3d_volume *dst_volume) ++{ ++ struct wined3d_map_desc src; ++ HRESULT hr; ++ struct wined3d_bo_address data; ++ struct wined3d_context *context; ++ ++ TRACE("device %p, src_volume %p, dst_volume %p.\n", ++ device, src_volume, dst_volume); ++#endif /* STAGING_CSMT */ + + if (src_volume->resource.format != dst_volume->resource.format) + { +@@ -3388,6 +3704,7 @@ + return WINED3DERR_INVALIDCALL; + } + ++#if defined(STAGING_CSMT) + /* Only a prepare, since we're uploading the entire volume. */ + wined3d_texture_prepare_texture(dst_volume->container, context, FALSE); + wined3d_resource_get_memory(&src_volume->resource, src_volume->resource.map_binding, &data); +@@ -3407,6 +3724,76 @@ + + /* Make sure that the destination texture is loaded. */ + wined3d_texture_load(dst_texture, context, FALSE); ++#else /* STAGING_CSMT */ ++ if (FAILED(hr = wined3d_volume_map(src_volume, &src, NULL, WINED3D_MAP_READONLY))) ++ return hr; ++ ++ context = context_acquire(device, NULL); ++ ++ /* Only a prepare, since we're uploading the entire volume. */ ++ wined3d_texture_prepare_texture(dst_volume->container, context, FALSE); ++ ++ data.buffer_object = 0; ++ data.addr = src.data; ++ wined3d_volume_upload_data(dst_volume, context, &data); ++ wined3d_volume_invalidate_location(dst_volume, ~WINED3D_LOCATION_TEXTURE_RGB); ++ ++ context_release(context); ++ ++ hr = wined3d_volume_unmap(src_volume); ++ ++ return hr; ++} ++ ++HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device, ++ struct wined3d_texture *src_texture, struct wined3d_texture *dst_texture) ++{ ++ enum wined3d_resource_type type; ++ unsigned int level_count, i; ++ HRESULT hr; ++ struct wined3d_context *context; ++ ++ TRACE("device %p, src_texture %p, dst_texture %p.\n", device, src_texture, dst_texture); ++ ++ /* Verify that the source and destination textures are non-NULL. */ ++ if (!src_texture || !dst_texture) ++ { ++ WARN("Source and destination textures must be non-NULL, returning WINED3DERR_INVALIDCALL.\n"); ++ return WINED3DERR_INVALIDCALL; ++ } ++ ++ if (src_texture->resource.pool != WINED3D_POOL_SYSTEM_MEM) ++ { ++ WARN("Source texture not in WINED3D_POOL_SYSTEM_MEM, returning WINED3DERR_INVALIDCALL.\n"); ++ return WINED3DERR_INVALIDCALL; ++ } ++ if (dst_texture->resource.pool != WINED3D_POOL_DEFAULT) ++ { ++ WARN("Destination texture not in WINED3D_POOL_DEFAULT, returning WINED3DERR_INVALIDCALL.\n"); ++ return WINED3DERR_INVALIDCALL; ++ } ++ ++ /* Verify that the source and destination textures are the same type. */ ++ type = src_texture->resource.type; ++ if (dst_texture->resource.type != type) ++ { ++ WARN("Source and destination have different types, returning WINED3DERR_INVALIDCALL.\n"); ++ return WINED3DERR_INVALIDCALL; ++ } ++ ++ /* Check that both textures have the identical numbers of levels. */ ++ level_count = wined3d_texture_get_level_count(src_texture); ++ if (wined3d_texture_get_level_count(dst_texture) != level_count) ++ { ++ WARN("Source and destination have different level counts, returning WINED3DERR_INVALIDCALL.\n"); ++ return WINED3DERR_INVALIDCALL; ++ } ++ ++ /* Make sure that the destination texture is loaded. */ ++ context = context_acquire(device, NULL); ++ wined3d_texture_load(dst_texture, context, FALSE); ++ context_release(context); ++#endif /* STAGING_CSMT */ + + /* Update every surface level of the texture. */ + switch (type) +@@ -3420,7 +3807,16 @@ + { + src_surface = surface_from_resource(wined3d_texture_get_sub_resource(src_texture, i)); + dst_surface = surface_from_resource(wined3d_texture_get_sub_resource(dst_texture, i)); ++#if defined(STAGING_CSMT) + surface_upload_from_surface(dst_surface, NULL, src_surface, NULL); ++#else /* STAGING_CSMT */ ++ hr = wined3d_device_update_surface(device, src_surface, NULL, dst_surface, NULL); ++ if (FAILED(hr)) ++ { ++ WARN("Failed to update surface, hr %#x.\n", hr); ++ return hr; ++ } ++#endif /* STAGING_CSMT */ + } + break; + } +@@ -3434,7 +3830,16 @@ + { + src_surface = surface_from_resource(wined3d_texture_get_sub_resource(src_texture, i)); + dst_surface = surface_from_resource(wined3d_texture_get_sub_resource(dst_texture, i)); ++#if defined(STAGING_CSMT) + surface_upload_from_surface(dst_surface, NULL, src_surface, NULL); ++#else /* STAGING_CSMT */ ++ hr = wined3d_device_update_surface(device, src_surface, NULL, dst_surface, NULL); ++ if (FAILED(hr)) ++ { ++ WARN("Failed to update surface, hr %#x.\n", hr); ++ return hr; ++ } ++#endif /* STAGING_CSMT */ + } + break; + } +@@ -3443,6 +3848,7 @@ + { + for (i = 0; i < level_count; ++i) + { ++#if defined(STAGING_CSMT) + HRESULT hr; + hr = device_update_volume(context, + volume_from_resource(wined3d_texture_get_sub_resource(src_texture, i)), +@@ -3451,6 +3857,15 @@ + { + WARN("Failed to update volume, hr %#x.\n", hr); + return; ++#else /* STAGING_CSMT */ ++ hr = device_update_volume(device, ++ volume_from_resource(wined3d_texture_get_sub_resource(src_texture, i)), ++ volume_from_resource(wined3d_texture_get_sub_resource(dst_texture, i))); ++ if (FAILED(hr)) ++ { ++ WARN("Failed to update volume, hr %#x.\n", hr); ++ return hr; ++#endif /* STAGING_CSMT */ + } + } + break; +@@ -3458,6 +3873,7 @@ + + default: + FIXME("Unsupported texture type %#x.\n", type); ++#if defined(STAGING_CSMT) + return; + } + } +@@ -3505,6 +3921,10 @@ + } + + wined3d_cs_emit_update_texture(device->cs, src_texture, dst_texture); ++#else /* STAGING_CSMT */ ++ return WINED3DERR_INVALIDCALL; ++ } ++#endif /* STAGING_CSMT */ + + return WINED3D_OK; + } +@@ -3567,8 +3987,13 @@ + if (state->render_states[WINED3D_RS_ZENABLE] || state->render_states[WINED3D_RS_ZWRITEENABLE] + || state->render_states[WINED3D_RS_STENCILENABLE]) + { ++#if defined(STAGING_CSMT) + struct wined3d_rendertarget_view *rt = state->fb.render_targets[0]; + struct wined3d_rendertarget_view *ds = state->fb.depth_stencil; ++#else /* STAGING_CSMT */ ++ struct wined3d_rendertarget_view *rt = device->fb.render_targets[0]; ++ struct wined3d_rendertarget_view *ds = device->fb.depth_stencil; ++#endif /* STAGING_CSMT */ + + if (ds && rt && (ds->width < rt->width || ds->height < rt->height)) + { +@@ -3665,6 +4090,7 @@ + struct wined3d_surface *src_surface, const RECT *src_rect, + struct wined3d_surface *dst_surface, const POINT *dst_point) + { ++#if defined(STAGING_CSMT) + const struct wined3d_format *src_format = src_surface->resource.format; + const struct wined3d_format *dst_format = dst_surface->resource.format; + UINT update_w, update_h; +@@ -3672,6 +4098,7 @@ + RECT r, dst_rect; + POINT p; + ++#endif /* STAGING_CSMT */ + TRACE("device %p, src_surface %p, src_rect %s, dst_surface %p, dst_point %s.\n", + device, src_surface, wine_dbgstr_rect(src_rect), + dst_surface, wine_dbgstr_point(dst_point)); +@@ -3683,6 +4110,7 @@ + return WINED3DERR_INVALIDCALL; + } + ++#if defined(STAGING_CSMT) + if (src_format->id != dst_format->id) + { + WARN("Source and destination surfaces should have the same format.\n"); +@@ -3745,6 +4173,9 @@ + wined3d_cs_emit_update_surface(device->cs, src_surface, src_rect, dst_surface, dst_point); + + return WINED3D_OK; ++#else /* STAGING_CSMT */ ++ return surface_upload_from_surface(dst_surface, dst_point, src_surface, src_rect); ++#endif /* STAGING_CSMT */ + } + + void CDECL wined3d_device_copy_resource(struct wined3d_device *device, +@@ -3846,8 +4277,14 @@ + rect = &r; + } + ++#if defined(STAGING_CSMT) + wined3d_cs_emit_clear_rtv(device->cs, view, rect, color); + return WINED3D_OK; ++#else /* STAGING_CSMT */ ++ resource = wined3d_texture_get_sub_resource(wined3d_texture_from_resource(resource), view->sub_resource_idx); ++ ++ return surface_color_fill(surface_from_resource(resource), rect, color); ++#endif /* STAGING_CSMT */ + } + + struct wined3d_rendertarget_view * CDECL wined3d_device_get_rendertarget_view(const struct wined3d_device *device, +@@ -3861,6 +4298,7 @@ + return NULL; + } + ++#if defined(STAGING_CSMT) + return device->state.fb.render_targets[view_idx]; + } + +@@ -3876,6 +4314,22 @@ + { + struct wined3d_rendertarget_view *prev; + struct wined3d_fb_state *fb = &device->state.fb; ++#else /* STAGING_CSMT */ ++ return device->fb.render_targets[view_idx]; ++} ++ ++struct wined3d_rendertarget_view * CDECL wined3d_device_get_depth_stencil_view(const struct wined3d_device *device) ++{ ++ TRACE("device %p.\n", device); ++ ++ return device->fb.depth_stencil; ++} ++ ++HRESULT CDECL wined3d_device_set_rendertarget_view(struct wined3d_device *device, ++ unsigned int view_idx, struct wined3d_rendertarget_view *view, BOOL set_viewport) ++{ ++ struct wined3d_rendertarget_view *prev; ++#endif /* STAGING_CSMT */ + + TRACE("device %p, view_idx %u, view %p, set_viewport %#x.\n", + device, view_idx, view, set_viewport); +@@ -3915,6 +4369,7 @@ + } + + ++#if defined(STAGING_CSMT) + prev = fb->render_targets[view_idx]; + if (view == prev) + return WINED3D_OK; +@@ -3922,6 +4377,15 @@ + if (view) + wined3d_rendertarget_view_incref(view); + fb->render_targets[view_idx] = view; ++#else /* STAGING_CSMT */ ++ prev = device->fb.render_targets[view_idx]; ++ if (view == prev) ++ return WINED3D_OK; ++ ++ if (view) ++ wined3d_rendertarget_view_incref(view); ++ device->fb.render_targets[view_idx] = view; ++#endif /* STAGING_CSMT */ + wined3d_cs_emit_set_rendertarget_view(device->cs, view_idx, view); + /* Release after the assignment, to prevent device_resource_released() + * from seeing the surface as still in use. */ +@@ -3933,6 +4397,7 @@ + + void CDECL wined3d_device_set_depth_stencil_view(struct wined3d_device *device, struct wined3d_rendertarget_view *view) + { ++#if defined(STAGING_CSMT) + struct wined3d_fb_state *fb = &device->state.fb; + struct wined3d_rendertarget_view *prev; + +@@ -3957,6 +4422,96 @@ + { + TRACE("device %p, x_hotspot %u, y_hotspot %u, cursor_image %p.\n", + device, x_hotspot, y_hotspot, cursor_image); ++#else /* STAGING_CSMT */ ++ struct wined3d_rendertarget_view *prev; ++ ++ TRACE("device %p, view %p.\n", device, view); ++ ++ prev = device->fb.depth_stencil; ++ if (prev == view) ++ { ++ TRACE("Trying to do a NOP SetRenderTarget operation.\n"); ++ return; ++ } ++ ++ if ((device->fb.depth_stencil = view)) ++ wined3d_rendertarget_view_incref(view); ++ wined3d_cs_emit_set_depth_stencil_view(device->cs, view); ++ if (prev) ++ wined3d_rendertarget_view_decref(prev); ++} ++ ++static struct wined3d_texture *wined3d_device_create_cursor_texture(struct wined3d_device *device, ++ struct wined3d_surface *cursor_image) ++{ ++ struct wined3d_resource_desc desc; ++ struct wined3d_map_desc map_desc; ++ struct wined3d_texture *texture; ++ struct wined3d_surface *surface; ++ BYTE *src_data, *dst_data; ++ unsigned int src_pitch; ++ unsigned int i; ++ ++ if (FAILED(wined3d_surface_map(cursor_image, &map_desc, NULL, WINED3D_MAP_READONLY))) ++ { ++ ERR("Failed to map source surface.\n"); ++ return NULL; ++ } ++ ++ src_pitch = map_desc.row_pitch; ++ src_data = map_desc.data; ++ ++ desc.resource_type = WINED3D_RTYPE_TEXTURE; ++ desc.format = WINED3DFMT_B8G8R8A8_UNORM; ++ desc.multisample_type = WINED3D_MULTISAMPLE_NONE; ++ desc.multisample_quality = 0; ++ desc.usage = WINED3DUSAGE_DYNAMIC; ++ desc.pool = WINED3D_POOL_DEFAULT; ++ desc.width = cursor_image->resource.width; ++ desc.height = cursor_image->resource.height; ++ desc.depth = 1; ++ desc.size = 0; ++ ++ if (FAILED(wined3d_texture_create(device, &desc, 1, WINED3D_SURFACE_MAPPABLE, ++ NULL, &wined3d_null_parent_ops, &texture))) ++ { ++ ERR("Failed to create cursor texture.\n"); ++ wined3d_surface_unmap(cursor_image); ++ return NULL; ++ } ++ ++ surface = surface_from_resource(wined3d_texture_get_sub_resource(texture, 0)); ++ if (FAILED(wined3d_surface_map(surface, &map_desc, NULL, WINED3D_MAP_DISCARD))) ++ { ++ ERR("Failed to map destination surface.\n"); ++ wined3d_texture_decref(texture); ++ wined3d_surface_unmap(cursor_image); ++ return NULL; ++ } ++ ++ dst_data = map_desc.data; ++ ++ for (i = 0; i < desc.height; ++i) ++ memcpy(&dst_data[map_desc.row_pitch * i], &src_data[src_pitch * i], desc.width * 4); ++ ++ wined3d_surface_unmap(surface); ++ wined3d_surface_unmap(cursor_image); ++ ++ return texture; ++} ++ ++HRESULT CDECL wined3d_device_set_cursor_properties(struct wined3d_device *device, ++ UINT x_hotspot, UINT y_hotspot, struct wined3d_surface *cursor_image) ++{ ++ TRACE("device %p, x_hotspot %u, y_hotspot %u, cursor_image %p.\n", ++ device, x_hotspot, y_hotspot, cursor_image); ++ ++ if (device->cursor_texture) ++ { ++ wined3d_texture_decref(device->cursor_texture); ++ device->cursor_texture = NULL; ++ } ++#endif /* STAGING_CSMT */ + + if (cursor_image) + { +@@ -3992,8 +4547,16 @@ + * release it after setting the cursor image. Windows doesn't + * addref the set surface, so we can't do this either without + * creating circular refcount dependencies. */ ++#if defined(STAGING_CSMT) + device->cursorWidth = cursor_image->resource.width; + device->cursorHeight = cursor_image->resource.height; ++#else /* STAGING_CSMT */ ++ if (!(device->cursor_texture = wined3d_device_create_cursor_texture(device, cursor_image))) ++ { ++ ERR("Failed to create cursor texture.\n"); ++ return WINED3DERR_INVALIDCALL; ++ } ++#endif /* STAGING_CSMT */ + + device->cursorWidth = cursor_image->resource.width; + device->cursorHeight = cursor_image->resource.height; +@@ -4093,6 +4656,12 @@ + else + SetCursor(NULL); + } ++#if !defined(STAGING_CSMT) ++ else if (device->cursor_texture) ++ { ++ device->bCursorVisible = show; ++ } ++#endif /* STAGING_CSMT */ + + return oldVisible; + } +@@ -4103,8 +4672,10 @@ + + TRACE("device %p.\n", device); + ++#if defined(STAGING_CSMT) + /* The resource list is manged by the main thread, iterate here and emit commands for + * each resource */ ++#endif /* STAGING_CSMT */ + LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &device->resources, struct wined3d_resource, resource_list_entry) + { + TRACE("Checking resource %p for eviction.\n", resource); +@@ -4112,6 +4683,7 @@ + if (resource->pool == WINED3D_POOL_MANAGED && !resource->map_count) + { + TRACE("Evicting %p.\n", resource); ++#if defined(STAGING_CSMT) + wined3d_cs_emit_evict_resource(device->cs, resource); + } + } +@@ -4130,6 +4702,37 @@ + + context = context_acquire(device, NULL); + gl_info = context->gl_info; ++#else /* STAGING_CSMT */ ++ resource->resource_ops->resource_unload(resource); ++ } ++ } ++ ++ /* Invalidate stream sources, the buffer(s) may have been evicted. */ ++ device_invalidate_state(device, STATE_STREAMSRC); ++} ++ ++static void delete_opengl_contexts(struct wined3d_device *device, struct wined3d_swapchain *swapchain) ++{ ++ struct wined3d_resource *resource, *cursor; ++ const struct wined3d_gl_info *gl_info; ++ struct wined3d_context *context; ++ struct wined3d_shader *shader; ++ ++ context = context_acquire(device, NULL); ++ gl_info = context->gl_info; ++ ++ LIST_FOR_EACH_ENTRY_SAFE(resource, cursor, &device->resources, struct wined3d_resource, resource_list_entry) ++ { ++ TRACE("Unloading resource %p.\n", resource); ++ ++ resource->resource_ops->resource_unload(resource); ++ } ++ ++ LIST_FOR_EACH_ENTRY(shader, &device->shaders, struct wined3d_shader, shader_list_entry) ++ { ++ device->shader_backend->shader_destroy(shader); ++ } ++#endif /* STAGING_CSMT */ + + if (device->depth_blt_texture) + { +@@ -4150,6 +4753,7 @@ + + HeapFree(GetProcessHeap(), 0, swapchain->context); + swapchain->context = NULL; ++#if defined(STAGING_CSMT) + swapchain->num_contexts = 0; + } + +@@ -4169,6 +4773,14 @@ + + static HRESULT create_primary_opengl_context(struct wined3d_device *device, struct wined3d_swapchain *swapchain) + { ++#else /* STAGING_CSMT */ ++} ++ ++static HRESULT create_primary_opengl_context(struct wined3d_device *device, struct wined3d_swapchain *swapchain) ++{ ++ struct wined3d_context *context; ++ struct wined3d_surface *target; ++#endif /* STAGING_CSMT */ + HRESULT hr; + + if (FAILED(hr = device->shader_backend->shader_alloc_private(device, +@@ -4185,6 +4797,7 @@ + return hr; + } + ++#if defined(STAGING_CSMT) + hr = wined3d_cs_emit_create_swapchain_context(device->cs, swapchain); + if (FAILED(hr)) + { +@@ -4195,6 +4808,34 @@ + } + + wined3d_cs_emit_create_dummy_textures(device->cs); ++#else /* STAGING_CSMT */ ++ /* Recreate the primary swapchain's context */ ++ swapchain->context = HeapAlloc(GetProcessHeap(), 0, sizeof(*swapchain->context)); ++ if (!swapchain->context) ++ { ++ ERR("Failed to allocate memory for swapchain context array.\n"); ++ device->blitter->free_private(device); ++ device->shader_backend->shader_free_private(device); ++ return E_OUTOFMEMORY; ++ } ++ ++ target = swapchain->back_buffers ++ ? surface_from_resource(wined3d_texture_get_sub_resource(swapchain->back_buffers[0], 0)) ++ : surface_from_resource(wined3d_texture_get_sub_resource(swapchain->front_buffer, 0)); ++ if (!(context = context_create(swapchain, target, swapchain->ds_format))) ++ { ++ WARN("Failed to create context.\n"); ++ device->blitter->free_private(device); ++ device->shader_backend->shader_free_private(device); ++ HeapFree(GetProcessHeap(), 0, swapchain->context); ++ return E_FAIL; ++ } ++ ++ swapchain->context[0] = context; ++ swapchain->num_contexts = 1; ++ create_dummy_textures(device, context); ++ context_release(context); ++#endif /* STAGING_CSMT */ + + return WINED3D_OK; + } +@@ -4214,8 +4855,10 @@ + unsigned int i; + + TRACE("device %p, swapchain_desc %p, mode %p, callback %p.\n", device, swapchain_desc, mode, callback); ++#if defined(STAGING_CSMT) + wined3d_cs_emit_glfinish(device->cs); + device->cs->ops->finish(device->cs); ++#endif /* STAGING_CSMT */ + + if (!(swapchain = wined3d_device_get_swapchain(device, 0))) + { +@@ -4231,9 +4874,21 @@ + wined3d_texture_decref(device->logo_texture); + device->logo_texture = NULL; + } ++#if defined(STAGING_CSMT) + } + + if (device->state.fb.render_targets) ++#else /* STAGING_CSMT */ ++ if (device->cursor_texture) ++ { ++ wined3d_texture_decref(device->cursor_texture); ++ device->cursor_texture = NULL; ++ } ++ state_unbind_resources(&device->state); ++ } ++ ++ if (device->fb.render_targets) ++#endif /* STAGING_CSMT */ + { + for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i) + { +@@ -4242,6 +4897,7 @@ + } + wined3d_device_set_depth_stencil_view(device, NULL); + ++#if defined(STAGING_CSMT) + if (reset_state) + { + state_unbind_resources(&device->state); +@@ -4251,6 +4907,12 @@ + { + wined3d_surface_decref(device->cs->onscreen_depth_stencil); + device->cs->onscreen_depth_stencil = NULL; ++#else /* STAGING_CSMT */ ++ if (device->onscreen_depth_stencil) ++ { ++ wined3d_surface_decref(device->onscreen_depth_stencil); ++ device->onscreen_depth_stencil = NULL; ++#endif /* STAGING_CSMT */ + } + + if (reset_state) +@@ -4263,6 +4925,7 @@ + } + } + ++#if defined(STAGING_CSMT) + /* Free implicit resources and wait for the command stream before modifying + * swapchain parameters. After modifying the swapchain parameters a new GL + * context may be acquired by the worker thread. This causes problems in the +@@ -4284,6 +4947,7 @@ + } + device->cs->ops->finish(device->cs); + ++#endif /* STAGING_CSMT */ + /* Is it necessary to recreate the gl context? Actually every setting can be changed + * on an existing gl context, so there's no real need for recreation. + * +@@ -4419,6 +5083,13 @@ + } + } + ++#if !defined(STAGING_CSMT) ++ if (device->auto_depth_stencil_view) ++ { ++ wined3d_rendertarget_view_decref(device->auto_depth_stencil_view); ++ device->auto_depth_stencil_view = NULL; ++ } ++#endif /* STAGING_CSMT */ + if (swapchain->desc.enable_auto_depth_stencil) + { + struct wined3d_resource_desc surface_desc; +@@ -4456,6 +5127,13 @@ + wined3d_device_set_depth_stencil_view(device, device->auto_depth_stencil_view); + } + ++#if !defined(STAGING_CSMT) ++ if (device->back_buffer_view) ++ { ++ wined3d_rendertarget_view_decref(device->back_buffer_view); ++ device->back_buffer_view = NULL; ++ } ++#endif /* STAGING_CSMT */ + if (swapchain->desc.backbuffer_count && FAILED(hr = wined3d_rendertarget_view_create_from_surface( + surface_from_resource(wined3d_texture_get_sub_resource(swapchain->back_buffers[0], 0)), + NULL, &wined3d_null_parent_ops, &device->back_buffer_view))) +@@ -4536,12 +5214,20 @@ + } + wined3d_cs_emit_reset_state(device->cs); + state_cleanup(&device->state); ++#if defined(STAGING_CSMT) + memset(&device->state, 0, sizeof(device->state)); + + if (device->d3d_initialized) + delete_opengl_contexts(device, swapchain); + + if (FAILED(hr = state_init(&device->state, &device->adapter->gl_info, ++#else /* STAGING_CSMT */ ++ ++ if (device->d3d_initialized) ++ delete_opengl_contexts(device, swapchain); ++ ++ if (FAILED(hr = state_init(&device->state, &device->fb, &device->adapter->gl_info, ++#endif /* STAGING_CSMT */ + &device->adapter->d3d_info, WINED3D_STATE_INIT_DEFAULT))) + ERR("Failed to initialize device state, hr %#x.\n", hr); + device->update_state = &device->state; +@@ -4550,6 +5236,7 @@ + } + else if (device->back_buffer_view) + { ++#if defined(STAGING_CSMT) + struct wined3d_state *state = &device->state; + + wined3d_device_set_rendertarget_view(device, 0, device->back_buffer_view, FALSE); +@@ -4565,6 +5252,24 @@ + state->scissor_rect.left = 0; + state->scissor_rect.right = swapchain->desc.backbuffer_width; + state->scissor_rect.bottom = swapchain->desc.backbuffer_height; ++#else /* STAGING_CSMT */ ++ struct wined3d_rendertarget_view *view = device->back_buffer_view; ++ struct wined3d_state *state = &device->state; ++ ++ wined3d_device_set_rendertarget_view(device, 0, view, FALSE); ++ ++ /* Note the min_z / max_z is not reset. */ ++ state->viewport.x = 0; ++ state->viewport.y = 0; ++ state->viewport.width = view->width; ++ state->viewport.height = view->height; ++ wined3d_cs_emit_set_viewport(device->cs, &state->viewport); ++ ++ state->scissor_rect.top = 0; ++ state->scissor_rect.left = 0; ++ state->scissor_rect.right = view->width; ++ state->scissor_rect.bottom = view->height; ++#endif /* STAGING_CSMT */ + wined3d_cs_emit_set_scissor_rect(device->cs, &state->scissor_rect); + } + +@@ -4643,6 +5348,10 @@ + + TRACE("device %p, resource %p, type %s.\n", device, resource, debug_d3dresourcetype(type)); + ++#if !defined(STAGING_CSMT) ++ context_resource_released(device, resource, type); ++ ++#endif /* STAGING_CSMT */ + switch (type) + { + case WINED3D_RTYPE_SURFACE: +@@ -4653,6 +5362,7 @@ + + for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i) + { ++#if defined(STAGING_CSMT) + if (wined3d_rendertarget_view_get_surface(device->state.fb.render_targets[i]) == surface) + { + ERR("Surface %p is still in use as render target %u.\n", surface, i); +@@ -4664,6 +5374,19 @@ + { + ERR("Surface %p is still in use as depth/stencil buffer.\n", surface); + device->state.fb.depth_stencil = NULL; ++#else /* STAGING_CSMT */ ++ if (wined3d_rendertarget_view_get_surface(device->fb.render_targets[i]) == surface) ++ { ++ ERR("Surface %p is still in use as render target %u.\n", surface, i); ++ device->fb.render_targets[i] = NULL; ++ } ++ } ++ ++ if (wined3d_rendertarget_view_get_surface(device->fb.depth_stencil) == surface) ++ { ++ ERR("Surface %p is still in use as depth/stencil buffer.\n", surface); ++ device->fb.depth_stencil = NULL; ++#endif /* STAGING_CSMT */ + } + } + break; +@@ -4804,7 +5527,11 @@ + + device->blitter = adapter->blitter; + ++#if defined(STAGING_CSMT) + if (FAILED(hr = state_init(&device->state, &adapter->gl_info, ++#else /* STAGING_CSMT */ ++ if (FAILED(hr = state_init(&device->state, &device->fb, &adapter->gl_info, ++#endif /* STAGING_CSMT */ + &adapter->d3d_info, WINED3D_STATE_INIT_DEFAULT))) + { + ERR("Failed to initialize device state, hr %#x.\n", hr); +@@ -4892,6 +5619,7 @@ + else + return CallWindowProcA(proc, window, message, wparam, lparam); + } ++#if defined(STAGING_CSMT) + + /* Context activation is done by the caller */ + struct wined3d_gl_bo *wined3d_device_get_bo(struct wined3d_device *device, UINT size, GLenum gl_usage, +@@ -4945,3 +5673,4 @@ + + wined3d_device_destroy_bo(device, context, bo); + } ++#endif /* STAGING_CSMT */ +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 +@@ -954,8 +954,15 @@ + const struct wined3d_shader_reg_maps *reg_maps, const struct shader_glsl_ctx_priv *ctx_priv) + { + const struct wined3d_shader_version *version = ®_maps->shader_version; ++#if defined(STAGING_CSMT) + const struct ps_compile_args *ps_args = ctx_priv->cur_ps_args; + const struct wined3d_gl_info *gl_info = context->gl_info; ++#else /* STAGING_CSMT */ ++ const struct wined3d_state *state = &shader->device->state; ++ const struct ps_compile_args *ps_args = ctx_priv->cur_ps_args; ++ const struct wined3d_gl_info *gl_info = context->gl_info; ++ const struct wined3d_fb_state *fb = &shader->device->fb; ++#endif /* STAGING_CSMT */ + unsigned int i, extra_constants_needed = 0; + const struct wined3d_shader_lconst *lconst; + const char *prefix; +@@ -1184,7 +1191,11 @@ + { + UINT in_count = min(vec4_varyings(version->major, gl_info), shader->limits->packed_input); + ++#if defined(STAGING_CSMT) + if (ps_args->vp_mode == vertexshader) ++#else /* STAGING_CSMT */ ++ if (use_vs(state)) ++#endif /* STAGING_CSMT */ + shader_addline(buffer, "varying vec4 %s_in[%u];\n", prefix, in_count); + else + /* TODO: Write a replacement shader for the fixed function +@@ -1231,6 +1242,7 @@ + } + else + { ++#if defined(STAGING_CSMT) + /* This happens because we do not have proper tracking of the + * constant registers that are actually used, only the max + * limit of the shader version. +@@ -1239,6 +1251,23 @@ + * it and just create the uniform. + */ + FIXME("Cannot find a free uniform for vpos correction params\n"); ++#else /* STAGING_CSMT */ ++ float ycorrection[] = ++ { ++ context->render_offscreen ? 0.0f : fb->render_targets[0]->height, ++ context->render_offscreen ? 1.0f : -1.0f, ++ 0.0f, ++ 0.0f, ++ }; ++ ++ /* This happens because we do not have proper tracking of the ++ * constant registers that are actually used, only the max ++ * limit of the shader version. */ ++ FIXME("Cannot find a free uniform for vpos correction params\n"); ++ shader_addline(buffer, "const vec4 ycorrection = "); ++ shader_glsl_append_imm_vec4(buffer, ycorrection); ++ shader_addline(buffer, ";\n"); ++#endif /* STAGING_CSMT */ + } + 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, +@@ -52,6 +59,7 @@ + WINED3D_CS_OP_SET_CLIP_PLANE, + 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, +@@ -130,6 +138,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 +@@ -152,6 +184,7 @@ + struct wined3d_cs_set_viewport + { + enum wined3d_cs_op opcode; ++#if defined(STAGING_CSMT) + struct wined3d_viewport viewport; + }; + +@@ -159,6 +192,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 +@@ -277,6 +319,7 @@ + { + enum wined3d_cs_op opcode; + enum wined3d_transform_state state; ++#if defined(STAGING_CSMT) + struct wined3d_matrix matrix; + }; + +@@ -291,6 +334,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 +@@ -298,6 +357,7 @@ + enum wined3d_cs_op opcode; + }; + ++#if defined(STAGING_CSMT) + struct wined3d_cs_set_consts_f + { + enum wined3d_cs_op opcode; +@@ -2649,192 +2709,864 @@ + /* 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_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, +-}; +- +-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; ++ const struct wined3d_cs_set_predication *op = data; + +- if (cs->thread_id == GetCurrentThreadId()) +- { +- static BOOL once; +- if (!once) +- { +- FIXME("flush_and_wait called from cs thread\n"); +- once = TRUE; +- } +- return; +- } ++ cs->state.predicate = op->predicate; ++ cs->state.predicate_value = op->value; ++} + +- wined3d_cs_emit_fence(cs, &fence); ++void wined3d_cs_emit_set_predication(struct wined3d_cs *cs, struct wined3d_query *predicate, BOOL value) ++{ ++ struct wined3d_cs_set_predication *op; + +- /* A busy wait should be fine, we're not supposed to have to wait very +- * long. */ +- while (!InterlockedCompareExchange(&fence, TRUE, TRUE)); ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_SET_PREDICATION; ++ op->predicate = predicate; ++ op->value = value; ++ ++ cs->ops->submit(cs); + } + +-static void wined3d_cs_mt_finish_prio(struct wined3d_cs *cs) ++static void wined3d_cs_exec_set_viewport(struct wined3d_cs *cs, const void *data) + { +- BOOL fence; ++ const struct wined3d_cs_set_viewport *op = data; + +- if (cs->thread_id == GetCurrentThreadId()) +- { +- static BOOL once; +- if (!once) +- { +- FIXME("flush_and_wait called from cs thread\n"); +- once = TRUE; +- } +- return; +- } ++ cs->state.viewport = *op->viewport; ++ device_invalidate_state(cs->device, STATE_VIEWPORT); ++} + +- wined3d_cs_emit_fence_prio(cs, &fence); ++void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport *viewport) ++{ ++ struct wined3d_cs_set_viewport *op; + +- /* A busy wait should be fine, we're not supposed to have to wait very +- * long. */ +- while (!InterlockedCompareExchange(&fence, TRUE, TRUE)); ++ op = cs->ops->require_space(cs, sizeof(*op)); ++ op->opcode = WINED3D_CS_OP_SET_VIEWPORT; ++ op->viewport = viewport; ++ ++ cs->ops->submit(cs); + } + +-static const struct wined3d_cs_ops wined3d_cs_mt_ops = ++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_surface_decref(device->onscreen_depth_stencil); ++ device->onscreen_depth_stencil = NULL; ++ } ++ } ++ } ++ ++ cs->fb.depth_stencil = op->view; ++ ++ if (!prev != !op->view) ++ { ++ /* Swapping NULL / non NULL depth stencil affects the depth and tests */ ++ device_invalidate_state(device, STATE_RENDER(WINED3D_RS_ZENABLE)); ++ device_invalidate_state(device, STATE_RENDER(WINED3D_RS_STENCILENABLE)); ++ device_invalidate_state(device, STATE_RENDER(WINED3D_RS_STENCILWRITEMASK)); ++ device_invalidate_state(device, STATE_RENDER(WINED3D_RS_DEPTHBIAS)); ++ } ++ else if (prev && prev->format->depth_size != op->view->format->depth_size) ++ { ++ 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; ++ ++ 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; ++ ++ 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_format->flags & WINED3DFMT_FLAG_SHADOW) != (old_format->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 (prev) ++ { ++ if (InterlockedDecrement(&prev->resource.bind_count) && prev->sampler == op->stage) ++ { ++ unsigned int i; ++ ++ /* Search for other stages the texture is bound to. Shouldn't ++ * happen if applications bind textures to a single stage only. */ ++ TRACE("Searching for other stages the texture is bound to.\n"); ++ for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i) ++ { ++ if (cs->state.textures[i] == prev) ++ { ++ TRACE("Texture is also bound to stage %u.\n", i); ++ prev->sampler = i; ++ break; ++ } ++ } ++ } ++ ++ if (!op->texture && op->stage < d3d_info->limits.ffp_blend_stages) ++ { ++ device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_COLOR_OP)); ++ device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_ALPHA_OP)); ++ } ++ } ++ ++ device_invalidate_state(cs->device, STATE_SAMPLER(op->stage)); ++} ++ ++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; ++} ++ ++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; ++} ++ ++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)); ++} ++ ++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->gl_info.limits.blends)) ++ 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_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_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, ++}; ++ ++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, +@@ -3059,5 +3791,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 +@@ -74,8 +74,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; + } + +@@ -131,6 +133,7 @@ + resource_unload(&texture->resource); + } + ++#if defined(STAGING_CSMT) + void wined3d_texture_cleanup_cs(struct wined3d_texture *texture) + { + wined3d_texture_unload_gl_texture(texture); +@@ -143,6 +146,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); + +@@ -154,8 +163,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) +@@ -522,10 +537,16 @@ + + if (!refcount) + { ++#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); ++#else /* STAGING_CSMT */ ++ wined3d_texture_cleanup(texture); ++ texture->resource.parent_ops->wined3d_object_destroyed(texture->resource.parent); ++ HeapFree(GetProcessHeap(), 0, texture); ++#endif /* STAGING_CSMT */ + } + + return refcount; +@@ -573,8 +594,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 */ + } + + void * CDECL wined3d_texture_get_parent(const struct wined3d_texture *texture) +@@ -603,6 +631,7 @@ + + if (texture->lod != lod) + { ++#if defined(STAGING_CSMT) + if (wined3d_settings.cs_multithreaded) + { + struct wined3d_device *device = texture->resource.device; +@@ -610,6 +639,7 @@ + device->cs->ops->finish(device->cs); + } + ++#endif /* STAGING_CSMT */ + texture->lod = lod; + + texture->texture_rgb.states[WINED3DTEXSTA_MAXMIPLEVEL] = ~0U; +@@ -669,12 +699,14 @@ + return WINED3DERR_INVALIDCALL; + } + ++#if defined(STAGING_CSMT) + if (wined3d_settings.cs_multithreaded) + { + FIXME("waiting for cs\n"); + texture->resource.device->cs->ops->finish(texture->resource.device->cs); + } + ++#endif /* STAGING_CSMT */ + if (color_key) + { + switch (flags & ~WINEDDCKEY_COLORSPACE) +@@ -762,10 +794,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; +@@ -843,6 +879,7 @@ + static void texture2d_sub_resource_load(struct wined3d_resource *sub_resource, + struct wined3d_context *context, BOOL srgb) + { ++#if defined(STAGING_CSMT) + surface_load(surface_from_resource(sub_resource), context, srgb); + } + +@@ -857,6 +894,19 @@ + 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_load(surface_from_resource(sub_resource), srgb); ++} ++ ++static void texture2d_sub_resource_add_dirty_region(struct wined3d_resource *sub_resource, ++ const struct wined3d_box *dirty_region) ++{ ++ struct wined3d_surface *surface = surface_from_resource(sub_resource); ++ ++ surface_prepare_map_memory(surface); ++ surface_load_location(surface, surface->resource.map_binding); ++ surface_invalidate_location(surface, ~surface->resource.map_binding); ++#endif /* STAGING_CSMT */ + } + + static void texture2d_sub_resource_cleanup(struct wined3d_resource *sub_resource) +@@ -868,7 +918,13 @@ + + 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); ++#else /* STAGING_CSMT */ ++ struct wined3d_surface *surface = surface_from_resource(sub_resource); ++ ++ surface_invalidate_location(surface, location); ++#endif /* STAGING_CSMT */ + } + + /* Context activation is done by the caller. */ +@@ -927,6 +983,7 @@ + + if (gl_info->supported[APPLE_CLIENT_STORAGE]) + { ++#if defined(STAGING_CSMT) + if (surface->flags & (SFLAG_NONPOW2) + || texture->flags & WINED3D_TEXTURE_CONVERTED) + { +@@ -935,12 +992,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; + +@@ -1008,6 +1079,7 @@ + wined3d_texture_unload_gl_texture(texture); + } + ++#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"); +@@ -1027,6 +1099,13 @@ + wined3d_texture_unload, + wined3d_texture_load_location_invalidated, + wined3d_texture_load_location, ++#else /* STAGING_CSMT */ ++static const struct wined3d_resource_ops texture_resource_ops = ++{ ++ texture_resource_incref, ++ texture_resource_decref, ++ wined3d_texture_unload, ++#endif /* STAGING_CSMT */ + }; + + static HRESULT cubetexture_init(struct wined3d_texture *texture, const struct wined3d_resource_desc *desc, +@@ -1043,6 +1122,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; + } +@@ -1051,6 +1131,14 @@ + { + WARN("(%p) : Tried to create not supported cube texture.\n", texture); + HeapFree(GetProcessHeap(), 0, texture); ++#else /* STAGING_CSMT */ ++ return WINED3DERR_INVALIDCALL; ++ } ++ ++ if (!gl_info->supported[ARB_TEXTURE_CUBE_MAP] && desc->pool != WINED3D_POOL_SCRATCH) ++ { ++ WARN("(%p) : Tried to create not supported cube texture.\n", texture); ++#endif /* STAGING_CSMT */ + return WINED3DERR_INVALIDCALL; + } + +@@ -1060,6 +1148,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; + } +@@ -1068,6 +1157,14 @@ + { + WARN("D3DUSAGE_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("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL.\n"); ++#endif /* STAGING_CSMT */ + return WINED3DERR_INVALIDCALL; + } + +@@ -1095,7 +1192,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; + } + } +@@ -1105,7 +1204,9 @@ + surface_flags, device, parent, parent_ops, &texture_resource_ops))) + { + WARN("Failed to initialize texture, returning %#x\n", hr); ++#if defined(STAGING_CSMT) + HeapFree(GetProcessHeap(), 0, texture); ++#endif /* STAGING_CSMT */ + return hr; + } + +@@ -1168,7 +1269,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; + } + +@@ -1199,7 +1302,9 @@ + else + { + WARN("Attempted to create a mipmapped NPOT texture without unconditional NPOT support.\n"); ++#if defined(STAGING_CSMT) + HeapFree(GetProcessHeap(), 0, texture); ++#endif /* STAGING_CSMT */ + return WINED3DERR_INVALIDCALL; + } + } +@@ -1212,6 +1317,7 @@ + if (!gl_info->supported[SGIS_GENERATE_MIPMAP]) + { + WARN("No mipmap generation support, returning WINED3DERR_INVALIDCALL.\n"); ++#if defined(STAGING_CSMT) + HeapFree(GetProcessHeap(), 0, texture); + return WINED3DERR_INVALIDCALL; + } +@@ -1220,6 +1326,14 @@ + { + WARN("D3DUSAGE_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("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning WINED3DERR_INVALIDCALL.\n"); ++#endif /* STAGING_CSMT */ + return WINED3DERR_INVALIDCALL; + } + +@@ -1235,7 +1349,9 @@ + surface_flags, device, parent, parent_ops, &texture_resource_ops))) + { + WARN("Failed to initialize texture, returning %#x.\n", hr); ++#if defined(STAGING_CSMT) + HeapFree(GetProcessHeap(), 0, texture); ++#endif /* STAGING_CSMT */ + return hr; + } + +@@ -1333,7 +1449,13 @@ + + 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); ++#else /* STAGING_CSMT */ ++ struct wined3d_volume *volume = volume_from_resource(sub_resource); ++ ++ wined3d_volume_invalidate_location(volume, location); ++#endif /* STAGING_CSMT */ + } + + static void texture3d_prepare_texture(struct wined3d_texture *texture, struct wined3d_context *context, BOOL srgb) +@@ -1351,7 +1473,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); +@@ -1396,6 +1522,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; + } +@@ -1404,6 +1531,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; + } + +@@ -1413,6 +1548,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; + } +@@ -1421,6 +1557,14 @@ + { + WARN("D3DUSAGE_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("D3DUSAGE_AUTOGENMIPMAP is set, and level count > 1, returning D3DERR_INVALIDCALL.\n"); ++#endif /* STAGING_CSMT */ + return WINED3DERR_INVALIDCALL; + } + +@@ -1455,7 +1599,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; + } + } +@@ -1465,7 +1611,9 @@ + 0, device, parent, parent_ops, &texture_resource_ops))) + { + WARN("Failed to initialize texture, returning %#x.\n", hr); ++#if defined(STAGING_CSMT) + HeapFree(GetProcessHeap(), 0, texture); ++#endif /* STAGING_CSMT */ + return hr; + } + +@@ -1536,6 +1684,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/surface.c b/dlls/wined3d/surface.c +--- a/dlls/wined3d/surface.c ++++ b/dlls/wined3d/surface.c +@@ -36,6 +36,7 @@ + + #define MAXLOCKCOUNT 50 /* After this amount of locks do not free the sysmem copy. */ + ++#if defined(STAGING_CSMT) + + static HRESULT surface_cpu_blt(struct wined3d_surface *dst_surface, const RECT *dst_rect, + struct wined3d_surface *src_surface, const RECT *src_rect, DWORD flags, +@@ -44,6 +45,20 @@ + void wined3d_surface_cleanup_cs(struct wined3d_surface *surface) + { + if (surface->rb_multisample || surface->rb_resolved || !list_empty(&surface->renderbuffers)) ++#else /* STAGING_CSMT */ ++static const DWORD surface_simple_locations = ++ WINED3D_LOCATION_SYSMEM | WINED3D_LOCATION_USER_MEMORY ++ | WINED3D_LOCATION_DIB | WINED3D_LOCATION_BUFFER; ++ ++static void surface_cleanup(struct wined3d_surface *surface) ++{ ++ struct wined3d_surface *overlay, *cur; ++ ++ TRACE("surface %p.\n", surface); ++ ++ if (surface->pbo || surface->rb_multisample ++ || surface->rb_resolved || !list_empty(&surface->renderbuffers)) ++#endif /* STAGING_CSMT */ + { + struct wined3d_renderbuffer_entry *entry, *entry2; + const struct wined3d_gl_info *gl_info; +@@ -52,6 +67,14 @@ + context = context_acquire(surface->resource.device, NULL); + gl_info = context->gl_info; + ++#if !defined(STAGING_CSMT) ++ if (surface->pbo) ++ { ++ TRACE("Deleting PBO %u.\n", surface->pbo); ++ GL_EXTCALL(glDeleteBuffersARB(1, &surface->pbo)); ++ } ++ ++#endif /* STAGING_CSMT */ + if (surface->rb_multisample) + { + TRACE("Deleting multisample renderbuffer %u.\n", surface->rb_multisample); +@@ -78,6 +101,7 @@ + { + DeleteDC(surface->hDC); + DeleteObject(surface->dib.DIBsection); ++#if defined(STAGING_CSMT) + surface->resource.bitmap_data = NULL; + } + +@@ -92,6 +116,10 @@ + BOOL user_mem = surface->resource.map_binding == WINED3D_LOCATION_USER_MEMORY; + + TRACE("surface %p.\n", surface); ++#else /* STAGING_CSMT */ ++ surface->dib.bitmap_data = NULL; ++ } ++#endif /* STAGING_CSMT */ + + if (surface->overlay_dest) + list_remove(&surface->overlay_entry); +@@ -103,6 +131,7 @@ + } + + resource_cleanup(&surface->resource); ++#if defined(STAGING_CSMT) + wined3d_cs_emit_surface_cleanup(cs, surface); + + /* Wait for the CS to finish operations on this surface when user memory was in use. +@@ -118,6 +147,17 @@ + + surface->resource.parent_ops->wined3d_object_destroyed(surface->resource.parent); + surface_cleanup(surface); ++#else /* STAGING_CSMT */ ++} ++ ++void wined3d_surface_destroy(struct wined3d_surface *surface) ++{ ++ TRACE("surface %p.\n", surface); ++ ++ surface_cleanup(surface); ++ surface->resource.parent_ops->wined3d_object_destroyed(surface->resource.parent); ++ HeapFree(GetProcessHeap(), 0, surface); ++#endif /* STAGING_CSMT */ + } + + void surface_get_drawable_size(const struct wined3d_surface *surface, const struct wined3d_context *context, +@@ -464,7 +504,11 @@ + TRACE("Creating a DIB section with size %dx%dx%d, size=%d.\n", + b_info->bmiHeader.biWidth, b_info->bmiHeader.biHeight, + b_info->bmiHeader.biBitCount, b_info->bmiHeader.biSizeImage); ++#if defined(STAGING_CSMT) + surface->dib.DIBsection = CreateDIBSection(0, b_info, DIB_RGB_COLORS, &surface->resource.bitmap_data, 0, 0); ++#else /* STAGING_CSMT */ ++ surface->dib.DIBsection = CreateDIBSection(0, b_info, DIB_RGB_COLORS, &surface->dib.bitmap_data, 0, 0); ++#endif /* STAGING_CSMT */ + + if (!surface->dib.DIBsection) + { +@@ -473,7 +517,11 @@ + return HRESULT_FROM_WIN32(GetLastError()); + } + ++#if defined(STAGING_CSMT) + TRACE("DIBSection at %p.\n", surface->resource.bitmap_data); ++#else /* STAGING_CSMT */ ++ TRACE("DIBSection at %p.\n", surface->dib.bitmap_data); ++#endif /* STAGING_CSMT */ + surface->dib.bitmap_size = b_info->bmiHeader.biSizeImage; + + HeapFree(GetProcessHeap(), 0, b_info); +@@ -487,6 +535,116 @@ + return WINED3D_OK; + } + ++#if !defined(STAGING_CSMT) ++static void surface_get_memory(const struct wined3d_surface *surface, struct wined3d_bo_address *data, ++ DWORD location) ++{ ++ if (location & WINED3D_LOCATION_BUFFER) ++ { ++ data->addr = NULL; ++ data->buffer_object = surface->pbo; ++ return; ++ } ++ if (location & WINED3D_LOCATION_USER_MEMORY) ++ { ++ data->addr = surface->user_memory; ++ data->buffer_object = 0; ++ return; ++ } ++ if (location & WINED3D_LOCATION_DIB) ++ { ++ data->addr = surface->dib.bitmap_data; ++ data->buffer_object = 0; ++ return; ++ } ++ if (location & WINED3D_LOCATION_SYSMEM) ++ { ++ data->addr = surface->resource.heap_memory; ++ data->buffer_object = 0; ++ return; ++ } ++ ++ ERR("Unexpected locations %s.\n", wined3d_debug_location(location)); ++ data->addr = NULL; ++ data->buffer_object = 0; ++} ++ ++static void surface_prepare_buffer(struct wined3d_surface *surface) ++{ ++ struct wined3d_context *context; ++ GLenum error; ++ const struct wined3d_gl_info *gl_info; ++ ++ if (surface->pbo) ++ return; ++ ++ context = context_acquire(surface->resource.device, NULL); ++ gl_info = context->gl_info; ++ ++ GL_EXTCALL(glGenBuffersARB(1, &surface->pbo)); ++ error = gl_info->gl_ops.gl.p_glGetError(); ++ if (!surface->pbo || error != GL_NO_ERROR) ++ ERR("Failed to create a PBO with error %s (%#x).\n", debug_glerror(error), error); ++ ++ TRACE("Binding PBO %u.\n", surface->pbo); ++ ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, surface->pbo)); ++ checkGLcall("glBindBufferARB"); ++ ++ GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, surface->resource.size + 4, ++ NULL, GL_STREAM_DRAW_ARB)); ++ checkGLcall("glBufferDataARB"); ++ ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); ++ checkGLcall("glBindBufferARB"); ++ ++ context_release(context); ++} ++ ++static void surface_prepare_system_memory(struct wined3d_surface *surface) ++{ ++ TRACE("surface %p.\n", surface); ++ ++ if (surface->resource.heap_memory) ++ return; ++ ++ /* Whatever surface we have, make sure that there is memory allocated ++ * for the downloaded copy, or a PBO to map. */ ++ if (!wined3d_resource_allocate_sysmem(&surface->resource)) ++ ERR("Failed to allocate system memory.\n"); ++ ++ if (surface->locations & WINED3D_LOCATION_SYSMEM) ++ ERR("Surface without system memory has WINED3D_LOCATION_SYSMEM set.\n"); ++} ++ ++void surface_prepare_map_memory(struct wined3d_surface *surface) ++{ ++ switch (surface->resource.map_binding) ++ { ++ case WINED3D_LOCATION_SYSMEM: ++ surface_prepare_system_memory(surface); ++ break; ++ ++ case WINED3D_LOCATION_USER_MEMORY: ++ if (!surface->user_memory) ++ ERR("Map binding is set to WINED3D_LOCATION_USER_MEMORY but surface->user_memory is NULL.\n"); ++ break; ++ ++ case WINED3D_LOCATION_DIB: ++ if (!surface->dib.bitmap_data) ++ ERR("Map binding is set to WINED3D_LOCATION_DIB but surface->dib.bitmap_data is NULL.\n"); ++ break; ++ ++ case WINED3D_LOCATION_BUFFER: ++ surface_prepare_buffer(surface); ++ break; ++ ++ default: ++ ERR("Unexpected map binding %s.\n", wined3d_debug_location(surface->resource.map_binding)); ++ } ++} ++ ++#endif /* STAGING_CSMT */ + static void surface_evict_sysmem(struct wined3d_surface *surface) + { + /* In some conditions the surface memory must not be freed: +@@ -499,8 +657,34 @@ + return; + + wined3d_resource_free_sysmem(&surface->resource); ++#if defined(STAGING_CSMT) + surface->resource.map_heap_memory = NULL; + wined3d_resource_invalidate_location(&surface->resource, WINED3D_LOCATION_SYSMEM); ++#else /* STAGING_CSMT */ ++ surface_invalidate_location(surface, WINED3D_LOCATION_SYSMEM); ++} ++ ++static void surface_release_client_storage(struct wined3d_surface *surface) ++{ ++ struct wined3d_context *context = context_acquire(surface->resource.device, NULL); ++ const struct wined3d_gl_info *gl_info = context->gl_info; ++ ++ if (surface->container->texture_rgb.name) ++ { ++ wined3d_texture_bind_and_dirtify(surface->container, context, FALSE); ++ gl_info->gl_ops.gl.p_glTexImage2D(surface->texture_target, surface->texture_level, ++ GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); ++ } ++ if (surface->container->texture_srgb.name) ++ { ++ wined3d_texture_bind_and_dirtify(surface->container, context, TRUE); ++ gl_info->gl_ops.gl.p_glTexImage2D(surface->texture_target, surface->texture_level, ++ GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); ++ } ++ wined3d_texture_force_reload(surface->container); ++ ++ context_release(context); ++#endif /* STAGING_CSMT */ + } + + static BOOL surface_use_pbo(const struct wined3d_surface *surface) +@@ -585,7 +769,11 @@ + } + + if (surface->resource.usage & WINED3DUSAGE_DEPTHSTENCIL) ++#if defined(STAGING_CSMT) + surface->resource.locations = WINED3D_LOCATION_DISCARDED; ++#else /* STAGING_CSMT */ ++ surface->locations = WINED3D_LOCATION_DISCARDED; ++#endif /* STAGING_CSMT */ + + if (surface_use_pbo(surface)) + surface->resource.map_binding = WINED3D_LOCATION_BUFFER; +@@ -593,6 +781,7 @@ + return WINED3D_OK; + } + ++#if defined(STAGING_CSMT) + static void surface_frontbuffer_updated(struct wined3d_surface *surface) + { + struct wined3d_context *context = NULL; +@@ -609,6 +798,50 @@ + wined3d_resource_load_location(&surface->resource, context, surface->container->resource.draw_binding); + if (context) + context_release(context); ++#else /* STAGING_CSMT */ ++static void surface_unmap(struct wined3d_surface *surface) ++{ ++ struct wined3d_device *device = surface->resource.device; ++ const struct wined3d_gl_info *gl_info; ++ struct wined3d_context *context; ++ ++ TRACE("surface %p.\n", surface); ++ ++ memset(&surface->lockedRect, 0, sizeof(surface->lockedRect)); ++ ++ switch (surface->resource.map_binding) ++ { ++ case WINED3D_LOCATION_SYSMEM: ++ case WINED3D_LOCATION_USER_MEMORY: ++ case WINED3D_LOCATION_DIB: ++ break; ++ ++ case WINED3D_LOCATION_BUFFER: ++ context = context_acquire(device, NULL); ++ gl_info = context->gl_info; ++ ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, surface->pbo)); ++ GL_EXTCALL(glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB)); ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); ++ checkGLcall("glUnmapBufferARB"); ++ context_release(context); ++ break; ++ ++ default: ++ ERR("Unexpected map binding %s.\n", wined3d_debug_location(surface->resource.map_binding)); ++ } ++ ++ if (surface->locations & (WINED3D_LOCATION_DRAWABLE | WINED3D_LOCATION_TEXTURE_RGB)) ++ { ++ TRACE("Not dirtified, nothing to do.\n"); ++ return; ++ } ++ ++ if (surface->container->swapchain && surface->container->swapchain->front_buffer == surface->container) ++ surface_load_location(surface, surface->container->resource.draw_binding); ++ else if (surface->resource.format->flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) ++ FIXME("Depth / stencil buffer locking is not implemented.\n"); ++#endif /* STAGING_CSMT */ + } + + static BOOL surface_is_full_rect(const struct wined3d_surface *surface, const RECT *r) +@@ -659,6 +892,14 @@ + if (src_mask & WINED3DFMT_FLAG_STENCIL) + gl_mask |= GL_STENCIL_BUFFER_BIT; + ++#if !defined(STAGING_CSMT) ++ /* Make sure the locations are up-to-date. Loading the destination ++ * surface isn't required if the entire surface is overwritten. */ ++ surface_load_location(src_surface, src_location); ++ if (!surface_is_full_rect(dst_surface, dst_rect)) ++ surface_load_location(dst_surface, dst_location); ++ ++#endif /* STAGING_CSMT */ + context = context_acquire(device, NULL); + if (!context->valid) + { +@@ -667,12 +908,14 @@ + return; + } + ++#if defined(STAGING_CSMT) + /* Make sure the locations are up-to-date. Loading the destination + * surface isn't required if the entire surface is overwritten. */ + wined3d_resource_load_location(&src_surface->resource, context, src_location); + if (!surface_is_full_rect(dst_surface, dst_rect)) + wined3d_resource_load_location(&dst_surface->resource, context, dst_location); + ++#endif /* STAGING_CSMT */ + gl_info = context->gl_info; + + context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, NULL, src_surface, src_location); +@@ -712,6 +955,7 @@ + context_release(context); + } + ++#if defined(STAGING_CSMT) + /* Blit between surface locations. Onscreen on different swapchains is not supported. + * Depth / stencil is not supported. Context activation is done by the caller. */ + static void surface_blt_fbo(const struct wined3d_device *device, +@@ -722,6 +966,16 @@ + const struct wined3d_gl_info *gl_info; + struct wined3d_context *context; + struct wined3d_surface *required_rt, *restore_rt; ++#else /* STAGING_CSMT */ ++/* Blit between surface locations. Onscreen on different swapchains is not supported. ++ * Depth / stencil is not supported. */ ++static void surface_blt_fbo(const struct wined3d_device *device, enum wined3d_texture_filter_type filter, ++ struct wined3d_surface *src_surface, DWORD src_location, const RECT *src_rect_in, ++ struct wined3d_surface *dst_surface, DWORD dst_location, const RECT *dst_rect_in) ++{ ++ const struct wined3d_gl_info *gl_info; ++ struct wined3d_context *context; ++#endif /* STAGING_CSMT */ + RECT src_rect, dst_rect; + GLenum gl_filter; + GLenum buffer; +@@ -760,6 +1014,7 @@ + * surface isn't required if the entire surface is overwritten. (And is + * in fact harmful if we're being called by surface_load_location() with + * the purpose of loading the destination surface.) */ ++#if defined(STAGING_CSMT) + wined3d_resource_load_location(&src_surface->resource, old_ctx, src_location); + if (!surface_is_full_rect(dst_surface, &dst_rect)) + wined3d_resource_load_location(&dst_surface->resource, old_ctx, dst_location); +@@ -778,6 +1033,15 @@ + restore_rt = NULL; + context = old_ctx; + } ++#else /* STAGING_CSMT */ ++ surface_load_location(src_surface, src_location); ++ if (!surface_is_full_rect(dst_surface, &dst_rect)) ++ surface_load_location(dst_surface, dst_location); ++ ++ if (src_location == WINED3D_LOCATION_DRAWABLE) context = context_acquire(device, src_surface); ++ else if (dst_location == WINED3D_LOCATION_DRAWABLE) context = context_acquire(device, dst_surface); ++ else context = context_acquire(device, NULL); ++#endif /* STAGING_CSMT */ + + if (!context->valid) + { +@@ -840,12 +1104,16 @@ + && dst_surface->container->swapchain->front_buffer == dst_surface->container)) + gl_info->gl_ops.gl.p_glFlush(); + ++#if defined(STAGING_CSMT) + if (restore_rt) + { + context_release(context); + context = context_acquire(device, restore_rt); + context_release(context); + } ++#else /* STAGING_CSMT */ ++ context_release(context); ++#endif /* STAGING_CSMT */ + } + + static BOOL fbo_blit_supported(const struct wined3d_gl_info *gl_info, enum wined3d_blit_op blit_op, +@@ -1022,6 +1290,18 @@ + return wined3d_surface_blt(surface, NULL, render_target, NULL, 0, NULL, WINED3D_TEXF_POINT); + } + ++#if !defined(STAGING_CSMT) ++/* Context activation is done by the caller. */ ++static void surface_remove_pbo(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info) ++{ ++ GL_EXTCALL(glDeleteBuffersARB(1, &surface->pbo)); ++ checkGLcall("glDeleteBuffersARB(1, &surface->pbo)"); ++ ++ surface->pbo = 0; ++ surface_invalidate_location(surface, WINED3D_LOCATION_BUFFER); ++} ++ ++#endif /* STAGING_CSMT */ + static ULONG surface_resource_incref(struct wined3d_resource *resource) + { + return wined3d_surface_incref(surface_from_resource(resource)); +@@ -1042,6 +1322,7 @@ + + TRACE("surface %p.\n", surface); + ++#if defined(STAGING_CSMT) + context = context_acquire(device, NULL); + gl_info = context->gl_info; + +@@ -1053,6 +1334,23 @@ + * opengl resources, so we cannot leave early. */ + wined3d_resource_validate_location(&surface->resource, WINED3D_LOCATION_DISCARDED); + wined3d_resource_invalidate_location(&surface->resource, ~WINED3D_LOCATION_DISCARDED); ++#else /* STAGING_CSMT */ ++ if (resource->pool == WINED3D_POOL_DEFAULT) ++ { ++ /* Default pool resources are supposed to be destroyed before Reset is called. ++ * Implicit resources stay however. So this means we have an implicit render target ++ * or depth stencil. The content may be destroyed, but we still have to tear down ++ * opengl resources, so we cannot leave early. ++ * ++ * Put the surfaces into sysmem, and reset the content. The D3D content is undefined, ++ * but we can't set the sysmem INDRAWABLE because when we're rendering the swapchain ++ * or the depth stencil into an FBO the texture or render buffer will be removed ++ * and all flags get lost */ ++ surface_prepare_system_memory(surface); ++ memset(surface->resource.heap_memory, 0, surface->resource.size); ++ surface_validate_location(surface, WINED3D_LOCATION_SYSMEM); ++ surface_invalidate_location(surface, ~WINED3D_LOCATION_SYSMEM); ++#endif /* STAGING_CSMT */ + + /* We also get here when the ddraw swapchain is destroyed, for example + * for a mode switch. In this case this surface won't necessarily be +@@ -1062,10 +1360,24 @@ + } + else + { ++#if defined(STAGING_CSMT) + wined3d_resource_prepare_map_memory(&surface->resource, context); + wined3d_resource_load_location(&surface->resource, context, surface->resource.map_binding); + wined3d_resource_invalidate_location(&surface->resource, ~surface->resource.map_binding); + } ++#else /* STAGING_CSMT */ ++ surface_prepare_map_memory(surface); ++ surface_load_location(surface, surface->resource.map_binding); ++ surface_invalidate_location(surface, ~surface->resource.map_binding); ++ } ++ ++ context = context_acquire(device, NULL); ++ gl_info = context->gl_info; ++ ++ /* Destroy PBOs, but load them into real sysmem before */ ++ if (surface->pbo) ++ surface_remove_pbo(surface, gl_info); ++#endif /* STAGING_CSMT */ + + /* Destroy fbo render buffers. This is needed for implicit render targets, for + * all application-created targets the application has to release the surface +@@ -1096,6 +1408,7 @@ + resource_unload(resource); + } + ++#if defined(STAGING_CSMT) + static void wined3d_surface_location_invalidated(struct wined3d_resource *resource, DWORD location) + { + struct wined3d_surface *surface = surface_from_resource(resource); +@@ -1111,6 +1424,19 @@ + { + surface_private_setup, + surface_frontbuffer_updated, ++#else /* STAGING_CSMT */ ++static const struct wined3d_resource_ops surface_resource_ops = ++{ ++ surface_resource_incref, ++ surface_resource_decref, ++ surface_unload, ++}; ++ ++static const struct wined3d_surface_ops surface_ops = ++{ ++ surface_private_setup, ++ surface_unmap, ++#endif /* STAGING_CSMT */ + }; + + /***************************************************************************** +@@ -1154,6 +1480,7 @@ + return WINED3D_OK; + } + ++#if defined(STAGING_CSMT) + static void gdi_surface_frontbuffer_updated(struct wined3d_surface *surface) + { + x11_copy_to_screen(surface->container->swapchain, &surface->lockedRect); +@@ -1163,6 +1490,23 @@ + { + gdi_surface_private_setup, + gdi_surface_frontbuffer_updated, ++#else /* STAGING_CSMT */ ++static void gdi_surface_unmap(struct wined3d_surface *surface) ++{ ++ TRACE("surface %p.\n", surface); ++ ++ /* Tell the swapchain to update the screen. */ ++ if (surface->container->swapchain && surface->container == surface->container->swapchain->front_buffer) ++ x11_copy_to_screen(surface->container->swapchain, &surface->lockedRect); ++ ++ memset(&surface->lockedRect, 0, sizeof(RECT)); ++} ++ ++static const struct wined3d_surface_ops gdi_surface_ops = ++{ ++ gdi_surface_private_setup, ++ gdi_surface_unmap, ++#endif /* STAGING_CSMT */ + }; + + /* This call just downloads data, the caller is responsible for binding the +@@ -1181,7 +1525,11 @@ + return; + } + ++#if defined(STAGING_CSMT) + wined3d_resource_get_memory(&surface->resource, dst_location, &data); ++#else /* STAGING_CSMT */ ++ surface_get_memory(surface, &data, dst_location); ++#endif /* STAGING_CSMT */ + + if (format->flags & WINED3DFMT_FLAG_COMPRESSED) + { +@@ -1430,6 +1778,7 @@ + } + } + ++#if defined(STAGING_CSMT) + BOOL surface_check_block_align(struct wined3d_surface *surface, const RECT *rect) + { + struct wined3d_box box; +@@ -1444,6 +1793,27 @@ + box.bottom = rect->bottom; + box.back = 1; + return wined3d_resource_check_block_align(&surface->resource, &box); ++#else /* STAGING_CSMT */ ++static BOOL surface_check_block_align(struct wined3d_surface *surface, const RECT *rect) ++{ ++ UINT width_mask, height_mask; ++ ++ if (!rect->left && !rect->top ++ && rect->right == surface->resource.width ++ && rect->bottom == surface->resource.height) ++ return TRUE; ++ ++ /* This assumes power of two block sizes, but NPOT block sizes would be ++ * silly anyway. */ ++ width_mask = surface->resource.format->block_width - 1; ++ height_mask = surface->resource.format->block_height - 1; ++ ++ if (!(rect->left & width_mask) && !(rect->top & height_mask) ++ && !(rect->right & width_mask) && !(rect->bottom & height_mask)) ++ return TRUE; ++ ++ return FALSE; ++#endif /* STAGING_CSMT */ + } + + HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface, const POINT *dst_point, +@@ -1526,11 +1896,17 @@ + return WINED3DERR_INVALIDCALL; + } + ++#if defined(STAGING_CSMT) + /* Use surface_cpu_blt() instead of uploading directly if we need + * conversion. Avoid calling wined3d_surface_blt() since that goes + * through the CS. */ + if (dst_format->convert || wined3d_format_get_color_key_conversion(dst_surface->container, FALSE)) + return surface_cpu_blt(dst_surface, &dst_rect, src_surface, src_rect, 0, NULL, WINED3D_TEXF_POINT); ++#else /* STAGING_CSMT */ ++ /* Use wined3d_surface_blt() instead of uploading directly if we need conversion. */ ++ if (dst_format->convert || wined3d_format_get_color_key_conversion(dst_surface->container, FALSE)) ++ return wined3d_surface_blt(dst_surface, &dst_rect, src_surface, src_rect, 0, NULL, WINED3D_TEXF_POINT); ++#endif /* STAGING_CSMT */ + + context = context_acquire(dst_surface->resource.device, NULL); + gl_info = context->gl_info; +@@ -1541,10 +1917,17 @@ + if (update_w == dst_w && update_h == dst_h) + wined3d_texture_prepare_texture(dst_surface->container, context, FALSE); + else ++#if defined(STAGING_CSMT) + wined3d_resource_load_location(&dst_surface->resource, context, WINED3D_LOCATION_TEXTURE_RGB); + wined3d_texture_bind(dst_surface->container, context, FALSE); + + wined3d_resource_get_memory(&src_surface->resource, src_surface->resource.locations, &data); ++#else /* STAGING_CSMT */ ++ surface_load_location(dst_surface, WINED3D_LOCATION_TEXTURE_RGB); ++ wined3d_texture_bind(dst_surface->container, context, FALSE); ++ ++ surface_get_memory(src_surface, &data, src_surface->locations); ++#endif /* STAGING_CSMT */ + wined3d_resource_get_pitch(&src_surface->resource, &src_row_pitch, &src_slice_pitch); + + surface_upload_data(dst_surface, gl_info, src_format, src_rect, src_row_pitch, dst_point, FALSE, &data); +@@ -1553,8 +1936,13 @@ + + context_release(context); + ++#if defined(STAGING_CSMT) + wined3d_resource_validate_location(&dst_surface->resource, WINED3D_LOCATION_TEXTURE_RGB); + wined3d_resource_invalidate_location(&dst_surface->resource, ~WINED3D_LOCATION_TEXTURE_RGB); ++#else /* STAGING_CSMT */ ++ surface_validate_location(dst_surface, WINED3D_LOCATION_TEXTURE_RGB); ++ surface_invalidate_location(dst_surface, ~WINED3D_LOCATION_TEXTURE_RGB); ++#endif /* STAGING_CSMT */ + + return WINED3D_OK; + } +@@ -1658,8 +2046,12 @@ + return GL_BACK; + } + ++#if defined(STAGING_CSMT) + /* Context activation is done by the caller. */ + void surface_load(struct wined3d_surface *surface, struct wined3d_context *context, BOOL srgb) ++#else /* STAGING_CSMT */ ++void surface_load(struct wined3d_surface *surface, BOOL srgb) ++#endif /* STAGING_CSMT */ + { + DWORD location = srgb ? WINED3D_LOCATION_TEXTURE_SRGB : WINED3D_LOCATION_TEXTURE_RGB; + BOOL ck_changed; +@@ -1683,6 +2075,7 @@ + /* To perform the color key conversion we need a sysmem copy of + * the surface. Make sure we have it. */ + ++#if defined(STAGING_CSMT) + wined3d_resource_prepare_map_memory(&surface->resource, context); + wined3d_resource_load_location(&surface->resource, context, surface->resource.map_binding); + wined3d_resource_invalidate_location(&surface->resource, ~surface->resource.map_binding); +@@ -1691,6 +2084,16 @@ + wined3d_texture_force_reload(surface->container); + } + else if (!(surface->resource.locations & location)) ++#else /* STAGING_CSMT */ ++ surface_prepare_map_memory(surface); ++ surface_load_location(surface, surface->resource.map_binding); ++ surface_invalidate_location(surface, ~surface->resource.map_binding); ++ /* Switching color keying on / off may change the internal format. */ ++ if (ck_changed) ++ wined3d_texture_force_reload(surface->container); ++ } ++ else if (!(surface->locations & location)) ++#endif /* STAGING_CSMT */ + { + TRACE("Reloading because surface is dirty.\n"); + } +@@ -1700,7 +2103,11 @@ + return; + } + ++#if defined(STAGING_CSMT) + wined3d_resource_load_location(&surface->resource, context, location); ++#else /* STAGING_CSMT */ ++ surface_load_location(surface, location); ++#endif /* STAGING_CSMT */ + surface_evict_sysmem(surface); + } + +@@ -1783,6 +2190,7 @@ + + void CDECL wined3d_surface_preload(struct wined3d_surface *surface) + { ++#if defined(STAGING_CSMT) + const struct wined3d_device *device = surface->resource.device; + TRACE("surface %p.\n", surface); + +@@ -1793,6 +2201,17 @@ + } + + wined3d_cs_emit_surface_preload(device->cs, surface); ++#else /* STAGING_CSMT */ ++ TRACE("surface %p.\n", surface); ++ ++ if (!surface->resource.device->d3d_initialized) ++ { ++ ERR("D3D not initialized.\n"); ++ return; ++ } ++ ++ wined3d_texture_preload(surface->container); ++#endif /* STAGING_CSMT */ + } + + void * CDECL wined3d_surface_get_parent(const struct wined3d_surface *surface) +@@ -2000,6 +2419,7 @@ + { + DeleteDC(surface->hDC); + DeleteObject(surface->dib.DIBsection); ++#if defined(STAGING_CSMT) + surface->resource.bitmap_data = NULL; + surface->flags &= ~SFLAG_DIBSECTION; + create_dib = TRUE; +@@ -2008,6 +2428,15 @@ + surface->resource.locations = 0; + wined3d_resource_free_sysmem(&surface->resource); + surface->resource.map_heap_memory = NULL; ++#else /* STAGING_CSMT */ ++ surface->dib.bitmap_data = NULL; ++ surface->flags &= ~SFLAG_DIBSECTION; ++ create_dib = TRUE; ++ } ++ ++ surface->locations = 0; ++ wined3d_resource_free_sysmem(&surface->resource); ++#endif /* STAGING_CSMT */ + + width = texture_resource->width; + height = texture_resource->height; +@@ -2033,7 +2462,11 @@ + else + surface->flags &= ~SFLAG_NONPOW2; + ++#if defined(STAGING_CSMT) + if ((surface->resource.user_memory = mem)) ++#else /* STAGING_CSMT */ ++ if ((surface->user_memory = mem)) ++#endif /* STAGING_CSMT */ + { + surface->resource.map_binding = WINED3D_LOCATION_USER_MEMORY; + valid_location = WINED3D_LOCATION_USER_MEMORY; +@@ -2069,11 +2502,19 @@ + + if (!valid_location) + { ++#if defined(STAGING_CSMT) + wined3d_resource_prepare_system_memory(&surface->resource); + valid_location = WINED3D_LOCATION_SYSMEM; + } + + wined3d_resource_validate_location(&surface->resource, valid_location); ++#else /* STAGING_CSMT */ ++ surface_prepare_system_memory(surface); ++ valid_location = WINED3D_LOCATION_SYSMEM; ++ } ++ ++ surface_validate_location(surface, valid_location); ++#endif /* STAGING_CSMT */ + + return WINED3D_OK; + } +@@ -2279,6 +2720,7 @@ + + static struct wined3d_texture *surface_convert_format(struct wined3d_surface *source, enum wined3d_format_id to_fmt) + { ++#if defined(STAGING_CSMT) + void *dst_data = NULL, *src_data = NULL; + UINT src_row_pitch, src_slice_pitch, dst_row_pitch, dst_slice_pitch; + const struct d3dfmt_converter_desc *conv; +@@ -2287,6 +2729,13 @@ + struct wined3d_surface *dst; + struct wined3d_context *context = NULL; + struct wined3d_device *device = source->resource.device; ++#else /* STAGING_CSMT */ ++ struct wined3d_map_desc src_map, dst_map; ++ const struct d3dfmt_converter_desc *conv; ++ struct wined3d_texture *ret = NULL; ++ struct wined3d_resource_desc desc; ++ struct wined3d_surface *dst; ++#endif /* STAGING_CSMT */ + + conv = find_converter(source->resource.format->id, to_fmt); + if (!conv) +@@ -2310,6 +2759,7 @@ + } + dst = surface_from_resource(wined3d_texture_get_sub_resource(ret, 0)); + ++#if defined(STAGING_CSMT) + wined3d_resource_get_pitch(&source->resource, &src_row_pitch, &src_slice_pitch); + wined3d_resource_get_pitch(&ret->resource, &dst_row_pitch, &dst_slice_pitch); + +@@ -2350,6 +2800,32 @@ + if (context) + context_release(context); + return NULL; ++#else /* STAGING_CSMT */ ++ memset(&src_map, 0, sizeof(src_map)); ++ memset(&dst_map, 0, sizeof(dst_map)); ++ ++ if (FAILED(wined3d_surface_map(source, &src_map, NULL, WINED3D_MAP_READONLY))) ++ { ++ ERR("Failed to lock the source surface.\n"); ++ wined3d_texture_decref(ret); ++ return NULL; ++ } ++ if (FAILED(wined3d_surface_map(dst, &dst_map, NULL, 0))) ++ { ++ ERR("Failed to lock the destination surface.\n"); ++ wined3d_surface_unmap(source); ++ wined3d_texture_decref(ret); ++ return NULL; ++ } ++ ++ conv->convert(src_map.data, dst_map.data, src_map.row_pitch, dst_map.row_pitch, ++ source->resource.width, source->resource.height); ++ ++ wined3d_surface_unmap(dst); ++ wined3d_surface_unmap(source); ++ ++ return ret; ++#endif /* STAGING_CSMT */ + } + + static HRESULT _Blt_ColorFill(BYTE *buf, unsigned int width, unsigned int height, +@@ -2417,6 +2893,7 @@ + + HRESULT CDECL wined3d_surface_unmap(struct wined3d_surface *surface) + { ++#if defined(STAGING_CSMT) + HRESULT hr; + TRACE("surface %p.\n", surface); + +@@ -2434,6 +2911,39 @@ + { + struct wined3d_box box; + const struct wined3d_format *format = surface->resource.format; ++#else /* STAGING_CSMT */ ++ TRACE("surface %p.\n", surface); ++ ++ if (!surface->resource.map_count) ++ { ++ WARN("Trying to unmap unmapped surface.\n"); ++ return WINEDDERR_NOTLOCKED; ++ } ++ --surface->resource.map_count; ++ ++ surface->surface_ops->surface_unmap(surface); ++ ++ return WINED3D_OK; ++} ++ ++HRESULT CDECL wined3d_surface_map(struct wined3d_surface *surface, ++ struct wined3d_map_desc *map_desc, const RECT *rect, DWORD flags) ++{ ++ const struct wined3d_format *format = surface->resource.format; ++ struct wined3d_device *device = surface->resource.device; ++ struct wined3d_context *context; ++ const struct wined3d_gl_info *gl_info; ++ BYTE *base_memory; ++ ++ TRACE("surface %p, map_desc %p, rect %s, flags %#x.\n", ++ surface, map_desc, wine_dbgstr_rect(rect), flags); ++ ++ if (surface->resource.map_count) ++ { ++ WARN("Surface is already mapped.\n"); ++ return WINED3DERR_INVALIDCALL; ++ } ++#endif /* STAGING_CSMT */ + + if ((format->flags & WINED3DFMT_FLAG_BLOCKS) && rect + && !surface_check_block_align(surface, rect)) +@@ -2445,6 +2955,13 @@ + return WINED3DERR_INVALIDCALL; + } + ++#if !defined(STAGING_CSMT) ++ ++surface->resource.map_count; ++ ++ if (!(surface->resource.access_flags & WINED3D_RESOURCE_ACCESS_CPU)) ++ WARN("Trying to lock unlockable surface.\n"); ++ ++#endif /* STAGING_CSMT */ + /* Performance optimization: Count how often a surface is mapped, if it is + * mapped regularly do not throw away the system memory copy. This avoids + * the need to download the surface from OpenGL all the time. The surface +@@ -2460,6 +2977,7 @@ + } + } + ++#if defined(STAGING_CSMT) + if (rect) + { + surface->lockedRect = *rect; +@@ -2524,22 +3042,121 @@ + WARN("Cannot use GetDC on a %s surface.\n", debug_d3dformat(surface->resource.format->id)); + return WINED3DERR_INVALIDCALL; + } ++#else /* STAGING_CSMT */ ++ surface_prepare_map_memory(surface); ++ if (flags & WINED3D_MAP_DISCARD) ++ { ++ TRACE("WINED3D_MAP_DISCARD flag passed, marking %s as up to date.\n", ++ wined3d_debug_location(surface->resource.map_binding)); ++ surface_validate_location(surface, surface->resource.map_binding); ++ } ++ else ++ { ++ if (surface->resource.usage & WINED3DUSAGE_DYNAMIC) ++ WARN_(d3d_perf)("Mapping a dynamic surface without WINED3D_MAP_DISCARD.\n"); + +- /* Give more detailed info for ddraw. */ +- if (surface->flags & SFLAG_DCINUSE) +- return WINEDDERR_DCALREADYCREATED; ++ surface_load_location(surface, surface->resource.map_binding); ++ } + +- /* Can't GetDC if the surface is locked. */ +- if (surface->resource.map_count) +- return WINED3DERR_INVALIDCALL; ++ if (!(flags & (WINED3D_MAP_NO_DIRTY_UPDATE | WINED3D_MAP_READONLY))) ++ surface_invalidate_location(surface, ~surface->resource.map_binding); + +- surface->flags |= SFLAG_DCINUSE; +- surface->resource.map_count++; +- wined3d_cs_emit_getdc(device->cs, surface); +- *dc = surface->hDC; +- TRACE("Returning dc %p.\n", *dc); ++ switch (surface->resource.map_binding) ++ { ++ case WINED3D_LOCATION_SYSMEM: ++ base_memory = surface->resource.heap_memory; ++ break; + +- return *dc ? WINED3D_OK : WINED3DERR_INVALIDCALL; ++ case WINED3D_LOCATION_USER_MEMORY: ++ base_memory = surface->user_memory; ++ break; ++ ++ case WINED3D_LOCATION_DIB: ++ base_memory = surface->dib.bitmap_data; ++ break; ++ ++ case WINED3D_LOCATION_BUFFER: ++ context = context_acquire(device, NULL); ++ gl_info = context->gl_info; ++ ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, surface->pbo)); ++ base_memory = GL_EXTCALL(glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_READ_WRITE_ARB)); ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); ++ checkGLcall("map PBO"); ++ ++ context_release(context); ++ break; ++ ++ default: ++ ERR("Unexpected map binding %s.\n", wined3d_debug_location(surface->resource.map_binding)); ++ base_memory = NULL; ++ } ++ ++ if (format->flags & WINED3DFMT_FLAG_BROKEN_PITCH) ++ map_desc->row_pitch = surface->resource.width * format->byte_count; ++ else ++ wined3d_resource_get_pitch(&surface->resource, &map_desc->row_pitch, &map_desc->slice_pitch); ++ map_desc->slice_pitch = 0; ++ ++ if (!rect) ++ { ++ map_desc->data = base_memory; ++ surface->lockedRect.left = 0; ++ surface->lockedRect.top = 0; ++ surface->lockedRect.right = surface->resource.width; ++ surface->lockedRect.bottom = surface->resource.height; ++ } ++ else ++ { ++ if ((format->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 ++ + ((rect->top / format->block_height) * map_desc->row_pitch) ++ + ((rect->left / format->block_width) * format->block_byte_count); ++ } ++ else ++ { ++ map_desc->data = base_memory ++ + (map_desc->row_pitch * rect->top) ++ + (rect->left * format->byte_count); ++ } ++ surface->lockedRect.left = rect->left; ++ surface->lockedRect.top = rect->top; ++ surface->lockedRect.right = rect->right; ++ surface->lockedRect.bottom = rect->bottom; ++ } ++ ++ TRACE("Locked rect %s.\n", wine_dbgstr_rect(&surface->lockedRect)); ++ TRACE("Returning memory %p, pitch %u.\n", map_desc->data, map_desc->row_pitch); ++ ++ return WINED3D_OK; ++} ++ ++HRESULT CDECL wined3d_surface_getdc(struct wined3d_surface *surface, HDC *dc) ++{ ++ HRESULT hr; ++ ++ TRACE("surface %p, dc %p.\n", surface, dc); ++#endif /* STAGING_CSMT */ ++ ++ /* Give more detailed info for ddraw. */ ++ if (surface->flags & SFLAG_DCINUSE) ++ return WINEDDERR_DCALREADYCREATED; ++ ++ /* Can't GetDC if the surface is locked. */ ++ if (surface->resource.map_count) ++ return WINED3DERR_INVALIDCALL; ++ ++#if defined(STAGING_CSMT) ++ surface->flags |= SFLAG_DCINUSE; ++ surface->resource.map_count++; ++ wined3d_cs_emit_getdc(device->cs, surface); ++ *dc = surface->hDC; ++ TRACE("Returning dc %p.\n", *dc); ++ ++ return *dc ? WINED3D_OK : WINED3DERR_INVALIDCALL; + } + + void wined3d_surface_releasedc_cs(struct wined3d_surface *surface) +@@ -2565,6 +3182,35 @@ + if (context) + context_release(context); + } ++#else /* STAGING_CSMT */ ++ /* Create a DIB section if there isn't a dc yet. */ ++ if (!surface->hDC) ++ { ++ if (surface->flags & SFLAG_CLIENT) ++ { ++ surface_load_location(surface, WINED3D_LOCATION_SYSMEM); ++ surface_release_client_storage(surface); ++ } ++ hr = surface_create_dib_section(surface); ++ if (FAILED(hr)) ++ return WINED3DERR_INVALIDCALL; ++ if (!(surface->resource.map_binding == WINED3D_LOCATION_USER_MEMORY ++ || surface->container->flags & WINED3D_TEXTURE_PIN_SYSMEM ++ || surface->pbo)) ++ surface->resource.map_binding = WINED3D_LOCATION_DIB; ++ } ++ ++ surface_load_location(surface, WINED3D_LOCATION_DIB); ++ surface_invalidate_location(surface, ~WINED3D_LOCATION_DIB); ++ ++ surface->flags |= SFLAG_DCINUSE; ++ surface->resource.map_count++; ++ ++ *dc = surface->hDC; ++ TRACE("Returning dc %p.\n", *dc); ++ ++ return WINED3D_OK; ++#endif /* STAGING_CSMT */ + } + + HRESULT CDECL wined3d_surface_releasedc(struct wined3d_surface *surface, HDC dc) +@@ -2584,6 +3230,7 @@ + surface->resource.map_count--; + surface->flags &= ~SFLAG_DCINUSE; + ++#if defined(STAGING_CSMT) + wined3d_cs_emit_releasedc(surface->resource.device->cs, surface); + + return WINED3D_OK; +@@ -2619,6 +3266,40 @@ + context = context_acquire(device, surface); + } + ++#else /* STAGING_CSMT */ ++ if (surface->resource.map_binding == WINED3D_LOCATION_USER_MEMORY ++ || (surface->container->flags & WINED3D_TEXTURE_PIN_SYSMEM ++ && surface->resource.map_binding != WINED3D_LOCATION_DIB)) ++ { ++ /* The game Salammbo modifies the surface contents without mapping the surface between ++ * a GetDC/ReleaseDC operation and flipping the surface. If the DIB remains the active ++ * copy and is copied to the screen, this update, which draws the mouse pointer, is lost. ++ * Do not only copy the DIB to the map location, but also make sure the map location is ++ * copied back to the DIB in the next getdc call. ++ * ++ * The same consideration applies to user memory surfaces. */ ++ surface_load_location(surface, surface->resource.map_binding); ++ surface_invalidate_location(surface, WINED3D_LOCATION_DIB); ++ } ++ ++ return WINED3D_OK; ++} ++ ++static void read_from_framebuffer(struct wined3d_surface *surface, DWORD dst_location) ++{ ++ struct wined3d_device *device = surface->resource.device; ++ const struct wined3d_gl_info *gl_info; ++ struct wined3d_context *context; ++ BYTE *mem; ++ BYTE *row, *top, *bottom; ++ int i; ++ BOOL srcIsUpsideDown; ++ struct wined3d_bo_address data; ++ ++ surface_get_memory(surface, &data, dst_location); ++ ++ context = context_acquire(device, surface); ++#endif /* STAGING_CSMT */ + context_apply_blit_state(context, device); + gl_info = context->gl_info; + +@@ -2706,12 +3387,16 @@ + checkGLcall("glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0)"); + } + ++#if defined(STAGING_CSMT) + if (restore_rt) + { + context_release(context); + context = context_acquire(device, restore_rt); + context_release(context); + } ++#else /* STAGING_CSMT */ ++ context_release(context); ++#endif /* STAGING_CSMT */ + } + + /* Read the framebuffer contents into a texture. Note that this function +@@ -2771,6 +3456,85 @@ + } + } + ++#if !defined(STAGING_CSMT) ++void flip_surface(struct wined3d_surface *front, struct wined3d_surface *back) ++{ ++ if (front->container->level_count != 1 || front->container->layer_count != 1 ++ || back->container->level_count != 1 || back->container->layer_count != 1) ++ ERR("Flip between surfaces %p and %p not supported.\n", front, back); ++ ++ /* Flip the surface contents */ ++ /* Flip the DC */ ++ { ++ HDC tmp; ++ tmp = front->hDC; ++ front->hDC = back->hDC; ++ back->hDC = tmp; ++ } ++ ++ /* Flip the DIBsection */ ++ { ++ HBITMAP tmp = front->dib.DIBsection; ++ front->dib.DIBsection = back->dib.DIBsection; ++ back->dib.DIBsection = tmp; ++ } ++ ++ /* Flip the surface data */ ++ { ++ void* tmp; ++ ++ tmp = front->dib.bitmap_data; ++ front->dib.bitmap_data = back->dib.bitmap_data; ++ back->dib.bitmap_data = tmp; ++ ++ tmp = front->resource.heap_memory; ++ front->resource.heap_memory = back->resource.heap_memory; ++ back->resource.heap_memory = tmp; ++ } ++ ++ /* Flip the PBO */ ++ { ++ GLuint tmp_pbo = front->pbo; ++ front->pbo = back->pbo; ++ back->pbo = tmp_pbo; ++ } ++ ++ /* Flip the opengl texture */ ++ { ++ GLuint tmp; ++ ++ tmp = back->container->texture_rgb.name; ++ back->container->texture_rgb.name = front->container->texture_rgb.name; ++ front->container->texture_rgb.name = tmp; ++ ++ tmp = back->container->texture_srgb.name; ++ back->container->texture_srgb.name = front->container->texture_srgb.name; ++ front->container->texture_srgb.name = tmp; ++ ++ tmp = back->rb_multisample; ++ back->rb_multisample = front->rb_multisample; ++ front->rb_multisample = tmp; ++ ++ tmp = back->rb_resolved; ++ back->rb_resolved = front->rb_resolved; ++ front->rb_resolved = tmp; ++ ++ resource_unload(&back->resource); ++ resource_unload(&front->resource); ++ } ++ ++ { ++ DWORD tmp_flags = back->flags; ++ back->flags = front->flags; ++ front->flags = tmp_flags; ++ ++ tmp_flags = back->locations; ++ back->locations = front->locations; ++ front->locations = tmp_flags; ++ } ++} ++ ++#endif /* STAGING_CSMT */ + /* Does a direct frame buffer -> texture copy. Stretching is done with single + * pixel copy calls. */ + static void fb_copy_to_texture_direct(struct wined3d_surface *dst_surface, struct wined3d_surface *src_surface, +@@ -2877,8 +3641,13 @@ + + /* The texture is now most up to date - If the surface is a render target + * and has a drawable, this path is never entered. */ ++#if defined(STAGING_CSMT) + wined3d_resource_validate_location(&dst_surface->resource, WINED3D_LOCATION_TEXTURE_RGB); + wined3d_resource_invalidate_location(&dst_surface->resource, ~WINED3D_LOCATION_TEXTURE_RGB); ++#else /* STAGING_CSMT */ ++ surface_validate_location(dst_surface, WINED3D_LOCATION_TEXTURE_RGB); ++ surface_invalidate_location(dst_surface, ~WINED3D_LOCATION_TEXTURE_RGB); ++#endif /* STAGING_CSMT */ + } + + /* Uses the hardware to stretch and flip the image */ +@@ -2946,7 +3715,11 @@ + checkGLcall("glEnable(texture_target)"); + + /* For now invalidate the texture copy of the back buffer. Drawable and sysmem copy are untouched */ ++#if defined(STAGING_CSMT) + wined3d_resource_invalidate_location(&src_surface->resource, WINED3D_LOCATION_TEXTURE_RGB); ++#else /* STAGING_CSMT */ ++ src_surface->locations &= ~WINED3D_LOCATION_TEXTURE_RGB; ++#endif /* STAGING_CSMT */ + } + + /* Make sure that the top pixel is always above the bottom pixel, and keep a separate upside down flag +@@ -3144,6 +3917,7 @@ + checkGLcall("glDeleteTextures(1, &backup)"); + } + ++#if defined(STAGING_CSMT) + if (wined3d_settings.cs_multithreaded) + gl_info->gl_ops.gl.p_glFinish(); + else if (wined3d_settings.strict_draw_ordering) +@@ -3155,6 +3929,17 @@ + * and has a drawable, this path is never entered. */ + wined3d_resource_validate_location(&dst_surface->resource, WINED3D_LOCATION_TEXTURE_RGB); + wined3d_resource_invalidate_location(&dst_surface->resource, ~WINED3D_LOCATION_TEXTURE_RGB); ++#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); ++ ++ /* The texture is now most up to date - If the surface is a render target ++ * and has a drawable, this path is never entered. */ ++ surface_validate_location(dst_surface, WINED3D_LOCATION_TEXTURE_RGB); ++ surface_invalidate_location(dst_surface, ~WINED3D_LOCATION_TEXTURE_RGB); ++#endif /* STAGING_CSMT */ + } + + /* Front buffer coordinates are always full screen coordinates, but our GL +@@ -3185,6 +3970,7 @@ + rect->bottom = drawable_height - rect->bottom; + } + ++#if defined(STAGING_CSMT) + /* Context activation is done by the caller. */ + static void surface_blt_to_drawable(const struct wined3d_device *device, + struct wined3d_context *old_ctx, +@@ -3219,6 +4005,26 @@ + /* Make sure the surface is up-to-date. This should probably use + * wined3d_resource_load_location() and worry about the destination + * surface too, unless we're overwriting it completely. */ ++#else /* STAGING_CSMT */ ++static void surface_blt_to_drawable(const struct wined3d_device *device, ++ enum wined3d_texture_filter_type filter, BOOL alpha_test, ++ struct wined3d_surface *src_surface, const RECT *src_rect_in, ++ struct wined3d_surface *dst_surface, const RECT *dst_rect_in) ++{ ++ const struct wined3d_gl_info *gl_info; ++ struct wined3d_context *context; ++ RECT src_rect, dst_rect; ++ ++ src_rect = *src_rect_in; ++ dst_rect = *dst_rect_in; ++ ++ context = context_acquire(device, dst_surface); ++ gl_info = context->gl_info; ++ ++ /* Make sure the surface is up-to-date. This should probably use ++ * surface_load_location() and worry about the destination surface too, ++ * unless we're overwriting it completely. */ ++#endif /* STAGING_CSMT */ + wined3d_texture_load(src_surface->container, context, FALSE); + + /* Activate the destination context, set it up for blitting */ +@@ -3261,6 +4067,7 @@ + /* Leave the opengl state valid for blitting */ + device->blitter->unset_shader(context->gl_info); + ++#if defined(STAGING_CSMT) + if (wined3d_settings.cs_multithreaded) + gl_info->gl_ops.gl.p_glFinish(); + else if (wined3d_settings.strict_draw_ordering +@@ -3274,6 +4081,14 @@ + context = context_acquire(device, restore_rt); + context_release(context); + } ++#else /* STAGING_CSMT */ ++ if (wined3d_settings.strict_draw_ordering ++ || (dst_surface->container->swapchain ++ && dst_surface->container->swapchain->front_buffer == dst_surface->container)) ++ gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ ++ ++ context_release(context); ++#endif /* STAGING_CSMT */ + } + + HRESULT surface_color_fill(struct wined3d_surface *s, const RECT *rect, const struct wined3d_color *color) +@@ -3297,9 +4112,15 @@ + enum wined3d_texture_filter_type filter) + { + struct wined3d_device *device = dst_surface->resource.device; ++#if defined(STAGING_CSMT) + const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; + struct wined3d_swapchain *src_swapchain, *dst_swapchain; + const struct wined3d_surface *rt = wined3d_rendertarget_view_get_surface(device->state.fb.render_targets[0]); ++#else /* STAGING_CSMT */ ++ const struct wined3d_surface *rt = wined3d_rendertarget_view_get_surface(device->fb.render_targets[0]); ++ const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; ++ struct wined3d_swapchain *src_swapchain, *dst_swapchain; ++#endif /* STAGING_CSMT */ + + TRACE("dst_surface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, blt_fx %p, filter %s.\n", + dst_surface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), +@@ -3424,7 +4245,9 @@ + /* Blit from offscreen surface to render target */ + struct wined3d_color_key old_blt_key = src_surface->container->src_blt_color_key; + DWORD old_color_key_flags = src_surface->container->color_key_flags; ++#if defined(STAGING_CSMT) + struct wined3d_context *context; ++#endif /* STAGING_CSMT */ + + TRACE("Blt from surface %p to rendertarget %p\n", src_surface, dst_surface); + +@@ -3458,6 +4281,7 @@ + wined3d_texture_set_color_key(src_surface->container, WINEDDSD_CKSRCBLT, NULL); + } + ++#if defined(STAGING_CSMT) + context = context_acquire(device, dst_surface); + surface_blt_to_drawable(device, context, filter, + flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYSRCOVERRIDE | WINEDDBLT_ALPHATEST), +@@ -3470,6 +4294,18 @@ + + wined3d_resource_validate_location(&dst_surface->resource, dst_surface->container->resource.draw_binding); + wined3d_resource_invalidate_location(&dst_surface->resource, ~dst_surface->container->resource.draw_binding); ++#else /* STAGING_CSMT */ ++ surface_blt_to_drawable(device, filter, ++ flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYSRCOVERRIDE | WINEDDBLT_ALPHATEST), ++ src_surface, src_rect, dst_surface, dst_rect); ++ ++ /* Restore the color key parameters */ ++ wined3d_texture_set_color_key(src_surface->container, WINEDDSD_CKSRCBLT, ++ (old_color_key_flags & WINEDDSD_CKSRCBLT) ? &old_blt_key : NULL); ++ ++ surface_validate_location(dst_surface, dst_surface->container->resource.draw_binding); ++ surface_invalidate_location(dst_surface, ~dst_surface->container->resource.draw_binding); ++#endif /* STAGING_CSMT */ + + return WINED3D_OK; + } +@@ -3544,6 +4380,7 @@ + { + TRACE("surface %p, new location %#x, w %u, h %u.\n", surface, location, w, h); + ++#if defined(STAGING_CSMT) + if (((surface->resource.locations & WINED3D_LOCATION_TEXTURE_RGB) && !(location & WINED3D_LOCATION_TEXTURE_RGB)) + || (!(surface->resource.locations & WINED3D_LOCATION_TEXTURE_RGB) + && (location & WINED3D_LOCATION_TEXTURE_RGB))) +@@ -3552,6 +4389,15 @@ + surface->ds_current_size.cx = w; + surface->ds_current_size.cy = h; + surface->resource.locations = location; ++#else /* STAGING_CSMT */ ++ if (((surface->locations & WINED3D_LOCATION_TEXTURE_RGB) && !(location & WINED3D_LOCATION_TEXTURE_RGB)) ++ || (!(surface->locations & WINED3D_LOCATION_TEXTURE_RGB) && (location & WINED3D_LOCATION_TEXTURE_RGB))) ++ wined3d_texture_set_dirty(surface->container); ++ ++ surface->ds_current_size.cx = w; ++ surface->ds_current_size.cy = h; ++ surface->locations = location; ++#endif /* STAGING_CSMT */ + } + + /* Context activation is done by the caller. */ +@@ -3566,7 +4412,11 @@ + /* TODO: Make this work for modes other than FBO */ + if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) return; + ++#if defined(STAGING_CSMT) + if (!(surface->resource.locations & location)) ++#else /* STAGING_CSMT */ ++ if (!(surface->locations & location)) ++#endif /* STAGING_CSMT */ + { + w = surface->ds_current_size.cx; + h = surface->ds_current_size.cy; +@@ -3592,7 +4442,11 @@ + return; + } + ++#if defined(STAGING_CSMT) + if (surface->resource.locations & WINED3D_LOCATION_DISCARDED) ++#else /* STAGING_CSMT */ ++ if (surface->locations & WINED3D_LOCATION_DISCARDED) ++#endif /* STAGING_CSMT */ + { + TRACE("Surface was discarded, no need copy data.\n"); + switch (location) +@@ -3609,6 +4463,7 @@ + default: + FIXME("Unhandled location %#x\n", location); + } ++#if defined(STAGING_CSMT) + surface->resource.locations &= ~WINED3D_LOCATION_DISCARDED; + surface->resource.locations |= location; + surface->ds_current_size.cx = surface->resource.width; +@@ -3620,6 +4475,19 @@ + { + FIXME("No up to date depth stencil location.\n"); + surface->resource.locations |= location; ++#else /* STAGING_CSMT */ ++ surface->locations &= ~WINED3D_LOCATION_DISCARDED; ++ surface->locations |= location; ++ surface->ds_current_size.cx = surface->resource.width; ++ surface->ds_current_size.cy = surface->resource.height; ++ return; ++ } ++ ++ if (!surface->locations) ++ { ++ FIXME("No up to date depth stencil location.\n"); ++ surface->locations |= location; ++#endif /* STAGING_CSMT */ + surface->ds_current_size.cx = surface->resource.width; + surface->ds_current_size.cy = surface->resource.height; + return; +@@ -3684,9 +4552,13 @@ + + context_invalidate_state(context, STATE_FRAMEBUFFER); + ++#if defined(STAGING_CSMT) + if (wined3d_settings.cs_multithreaded) + gl_info->gl_ops.gl.p_glFinish(); + else if (wined3d_settings.strict_draw_ordering) ++#else /* STAGING_CSMT */ ++ if (wined3d_settings.strict_draw_ordering) ++#endif /* STAGING_CSMT */ + gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ + } + else if (location == WINED3D_LOCATION_DRAWABLE) +@@ -3702,9 +4574,13 @@ + + context_invalidate_state(context, STATE_FRAMEBUFFER); + ++#if defined(STAGING_CSMT) + if (wined3d_settings.cs_multithreaded) + gl_info->gl_ops.gl.p_glFinish(); + else if (wined3d_settings.strict_draw_ordering) ++#else /* STAGING_CSMT */ ++ if (wined3d_settings.strict_draw_ordering) ++#endif /* STAGING_CSMT */ + gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ + } + else +@@ -3712,6 +4588,7 @@ + ERR("Invalid location (%#x) specified.\n", location); + } + ++#if defined(STAGING_CSMT) + surface->resource.locations |= location; + surface->ds_current_size.cx = surface->resource.width; + surface->ds_current_size.cy = surface->resource.height; +@@ -3757,6 +4634,135 @@ + TRACE("Surface was discarded, nothing to do.\n"); + return WINED3D_OK; + } ++#else /* STAGING_CSMT */ ++ surface->locations |= location; ++ surface->ds_current_size.cx = surface->resource.width; ++ surface->ds_current_size.cy = surface->resource.height; ++} ++ ++void surface_validate_location(struct wined3d_surface *surface, DWORD location) ++{ ++ TRACE("surface %p, location %s.\n", surface, wined3d_debug_location(location)); ++ ++ surface->locations |= location; ++} ++ ++void surface_invalidate_location(struct wined3d_surface *surface, DWORD location) ++{ ++ TRACE("surface %p, location %s.\n", surface, wined3d_debug_location(location)); ++ ++ if (location & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) ++ wined3d_texture_set_dirty(surface->container); ++ surface->locations &= ~location; ++ ++ if (!surface->locations) ++ ERR("Surface %p does not have any up to date location.\n", surface); ++} ++ ++static DWORD resource_access_from_location(DWORD location) ++{ ++ switch (location) ++ { ++ case WINED3D_LOCATION_SYSMEM: ++ case WINED3D_LOCATION_USER_MEMORY: ++ case WINED3D_LOCATION_DIB: ++ case WINED3D_LOCATION_BUFFER: ++ return WINED3D_RESOURCE_ACCESS_CPU; ++ ++ case WINED3D_LOCATION_DRAWABLE: ++ case WINED3D_LOCATION_TEXTURE_SRGB: ++ case WINED3D_LOCATION_TEXTURE_RGB: ++ case WINED3D_LOCATION_RB_MULTISAMPLE: ++ case WINED3D_LOCATION_RB_RESOLVED: ++ return WINED3D_RESOURCE_ACCESS_GPU; ++ ++ default: ++ FIXME("Unhandled location %#x.\n", location); ++ return 0; ++ } ++} ++ ++static void surface_copy_simple_location(struct wined3d_surface *surface, DWORD location) ++{ ++ struct wined3d_device *device = surface->resource.device; ++ struct wined3d_context *context; ++ const struct wined3d_gl_info *gl_info; ++ struct wined3d_bo_address dst, src; ++ UINT size = surface->resource.size; ++ ++ surface_get_memory(surface, &dst, location); ++ surface_get_memory(surface, &src, surface->locations); ++ ++ if (dst.buffer_object) ++ { ++ context = context_acquire(device, NULL); ++ gl_info = context->gl_info; ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, dst.buffer_object)); ++ GL_EXTCALL(glBufferSubDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0, size, src.addr)); ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0)); ++ checkGLcall("Upload PBO"); ++ context_release(context); ++ return; ++ } ++ if (src.buffer_object) ++ { ++ context = context_acquire(device, NULL); ++ gl_info = context->gl_info; ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, src.buffer_object)); ++ GL_EXTCALL(glGetBufferSubDataARB(GL_PIXEL_PACK_BUFFER_ARB, 0, size, dst.addr)); ++ GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0)); ++ checkGLcall("Download PBO"); ++ context_release(context); ++ return; ++ } ++ memcpy(dst.addr, src.addr, size); ++} ++ ++static void surface_load_sysmem(struct wined3d_surface *surface, ++ const struct wined3d_gl_info *gl_info, DWORD dst_location) ++{ ++ if (surface->locations & surface_simple_locations) ++ { ++ surface_copy_simple_location(surface, dst_location); ++ return; ++ } ++ ++ if (surface->locations & (WINED3D_LOCATION_RB_MULTISAMPLE | WINED3D_LOCATION_RB_RESOLVED)) ++ surface_load_location(surface, WINED3D_LOCATION_TEXTURE_RGB); ++ ++ /* Download the surface to system memory. */ ++ if (surface->locations & (WINED3D_LOCATION_TEXTURE_RGB | WINED3D_LOCATION_TEXTURE_SRGB)) ++ { ++ struct wined3d_device *device = surface->resource.device; ++ struct wined3d_context *context; ++ ++ /* TODO: Use already acquired context when possible. */ ++ context = context_acquire(device, NULL); ++ ++ wined3d_texture_bind_and_dirtify(surface->container, context, ++ !(surface->locations & WINED3D_LOCATION_TEXTURE_RGB)); ++ surface_download_data(surface, gl_info, dst_location); ++ ++ context_release(context); ++ ++ return; ++ } ++ ++ if (surface->locations & WINED3D_LOCATION_DRAWABLE) ++ { ++ read_from_framebuffer(surface, dst_location); ++ return; ++ } ++ ++ FIXME("Can't load surface %p with location flags %s into sysmem.\n", ++ surface, wined3d_debug_location(surface->locations)); ++} ++ ++static HRESULT surface_load_drawable(struct wined3d_surface *surface, ++ const struct wined3d_gl_info *gl_info) ++{ ++ RECT r; ++#endif /* STAGING_CSMT */ + + if (wined3d_settings.offscreen_rendering_mode == ORM_FBO + && wined3d_resource_is_offscreen(&surface->container->resource)) +@@ -3766,6 +4772,7 @@ + } + + surface_get_rect(surface, NULL, &r); ++#if defined(STAGING_CSMT) + wined3d_resource_load_location(&surface->resource, context, WINED3D_LOCATION_TEXTURE_RGB); + surface_blt_to_drawable(surface->resource.device, context, + WINED3D_TEXF_POINT, FALSE, surface, &r, surface, &r); +@@ -3834,6 +4841,66 @@ + RECT rect = {0, 0, surface->resource.width, surface->resource.height}; + + surface_blt_fbo(device, context, WINED3D_TEXF_POINT, surface, src_location, ++#else /* STAGING_CSMT */ ++ surface_load_location(surface, WINED3D_LOCATION_TEXTURE_RGB); ++ surface_blt_to_drawable(surface->resource.device, ++ WINED3D_TEXF_POINT, FALSE, surface, &r, surface, &r); ++ ++ return WINED3D_OK; ++} ++ ++static HRESULT surface_load_texture(struct wined3d_surface *surface, ++ const struct wined3d_gl_info *gl_info, BOOL srgb) ++{ ++ RECT src_rect = {0, 0, surface->resource.width, surface->resource.height}; ++ struct wined3d_device *device = surface->resource.device; ++ const struct wined3d_color_key_conversion *conversion; ++ struct wined3d_texture *texture = surface->container; ++ struct wined3d_context *context; ++ UINT width, src_row_pitch, src_slice_pitch, dst_pitch; ++ struct wined3d_bo_address data; ++ struct wined3d_format format; ++ POINT dst_point = {0, 0}; ++ BYTE *mem = NULL; ++ ++ if (wined3d_settings.offscreen_rendering_mode != ORM_FBO ++ && wined3d_resource_is_offscreen(&texture->resource) ++ && (surface->locations & WINED3D_LOCATION_DRAWABLE)) ++ { ++ surface_load_fb_texture(surface, srgb); ++ ++ return WINED3D_OK; ++ } ++ ++ if (surface->locations & (WINED3D_LOCATION_TEXTURE_SRGB | WINED3D_LOCATION_TEXTURE_RGB) ++ && (surface->resource.format->flags & WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB) ++ && fbo_blit_supported(gl_info, WINED3D_BLIT_OP_COLOR_BLIT, ++ NULL, surface->resource.usage, surface->resource.pool, surface->resource.format, ++ NULL, surface->resource.usage, surface->resource.pool, surface->resource.format)) ++ { ++ if (srgb) ++ surface_blt_fbo(device, WINED3D_TEXF_POINT, surface, WINED3D_LOCATION_TEXTURE_RGB, ++ &src_rect, surface, WINED3D_LOCATION_TEXTURE_SRGB, &src_rect); ++ else ++ surface_blt_fbo(device, WINED3D_TEXF_POINT, surface, WINED3D_LOCATION_TEXTURE_SRGB, ++ &src_rect, surface, WINED3D_LOCATION_TEXTURE_RGB, &src_rect); ++ ++ return WINED3D_OK; ++ } ++ ++ if (surface->locations & (WINED3D_LOCATION_RB_MULTISAMPLE | WINED3D_LOCATION_RB_RESOLVED) ++ && (!srgb || (surface->resource.format->flags & WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB)) ++ && fbo_blit_supported(gl_info, WINED3D_BLIT_OP_COLOR_BLIT, ++ NULL, surface->resource.usage, surface->resource.pool, surface->resource.format, ++ NULL, surface->resource.usage, surface->resource.pool, surface->resource.format)) ++ { ++ DWORD src_location = surface->locations & WINED3D_LOCATION_RB_RESOLVED ? ++ WINED3D_LOCATION_RB_RESOLVED : WINED3D_LOCATION_RB_MULTISAMPLE; ++ DWORD dst_location = srgb ? WINED3D_LOCATION_TEXTURE_SRGB : WINED3D_LOCATION_TEXTURE_RGB; ++ RECT rect = {0, 0, surface->resource.width, surface->resource.height}; ++ ++ surface_blt_fbo(device, WINED3D_TEXF_POINT, surface, src_location, ++#endif /* STAGING_CSMT */ + &rect, surface, dst_location, &rect); + + return WINED3D_OK; +@@ -3843,6 +4910,7 @@ + + if (srgb) + { ++#if defined(STAGING_CSMT) + if ((surface->resource.locations & (WINED3D_LOCATION_TEXTURE_RGB | surface->resource.map_binding)) + == WINED3D_LOCATION_TEXTURE_RGB) + { +@@ -3871,6 +4939,39 @@ + wined3d_resource_prepare_system_memory(&surface->resource); + wined3d_resource_load_location(&surface->resource, context, WINED3D_LOCATION_SYSMEM); + } ++#else /* STAGING_CSMT */ ++ if ((surface->locations & (WINED3D_LOCATION_TEXTURE_RGB | surface->resource.map_binding)) ++ == WINED3D_LOCATION_TEXTURE_RGB) ++ { ++ /* Performance warning... */ ++ FIXME("Downloading RGB surface %p to reload it as sRGB.\n", surface); ++ surface_prepare_map_memory(surface); ++ surface_load_location(surface, surface->resource.map_binding); ++ } ++ } ++ else ++ { ++ if ((surface->locations & (WINED3D_LOCATION_TEXTURE_SRGB | surface->resource.map_binding)) ++ == WINED3D_LOCATION_TEXTURE_SRGB) ++ { ++ /* Performance warning... */ ++ FIXME("Downloading sRGB surface %p to reload it as RGB.\n", surface); ++ surface_prepare_map_memory(surface); ++ surface_load_location(surface, surface->resource.map_binding); ++ } ++ } ++ ++ if (!(surface->locations & surface_simple_locations)) ++ { ++ WARN("Trying to load a texture from sysmem, but no simple location is valid.\n"); ++ /* Lets hope we get it from somewhere... */ ++ surface_prepare_system_memory(surface); ++ surface_load_location(surface, WINED3D_LOCATION_SYSMEM); ++ } ++ ++ /* TODO: Use already acquired context when possible. */ ++ context = context_acquire(device, NULL); ++#endif /* STAGING_CSMT */ + + wined3d_texture_prepare_texture(texture, context, srgb); + wined3d_texture_bind_and_dirtify(texture, context, srgb); +@@ -3892,7 +4993,11 @@ + /* Don't use PBOs for converted surfaces. During PBO conversion we look at + * WINED3D_TEXTURE_CONVERTED but it isn't set (yet) in all cases it is + * getting called. */ ++#if defined(STAGING_CSMT) + if ((format.convert || conversion) && surface->resource.buffer) ++#else /* STAGING_CSMT */ ++ if ((format.convert || conversion) && surface->pbo) ++#endif /* STAGING_CSMT */ + { + TRACE("Removing the pbo attached to surface %p.\n", surface); + +@@ -3901,6 +5006,7 @@ + else + surface->resource.map_binding = WINED3D_LOCATION_SYSMEM; + ++#if defined(STAGING_CSMT) + wined3d_resource_prepare_map_memory(&surface->resource, context); + wined3d_resource_load_location(&surface->resource, context, surface->resource.map_binding); + wined3d_resource_free_bo(&surface->resource); +@@ -3908,6 +5014,14 @@ + } + + wined3d_resource_get_memory(&surface->resource, surface->resource.locations, &data); ++#else /* STAGING_CSMT */ ++ surface_prepare_map_memory(surface); ++ surface_load_location(surface, surface->resource.map_binding); ++ surface_remove_pbo(surface, gl_info); ++ } ++ ++ surface_get_memory(surface, &data, surface->locations); ++#endif /* STAGING_CSMT */ + if (format.convert) + { + /* This code is entered for texture formats which need a fixup. */ +@@ -3953,6 +5067,7 @@ + + surface_upload_data(surface, gl_info, &format, &src_rect, src_row_pitch, &dst_point, srgb, &data); + ++#if defined(STAGING_CSMT) + HeapFree(GetProcessHeap(), 0, mem); + + return WINED3D_OK; +@@ -3976,6 +5091,31 @@ + struct wined3d_context *context, DWORD location) + { + struct wined3d_surface *surface = surface_from_resource(resource); ++#else /* STAGING_CSMT */ ++ context_release(context); ++ ++ HeapFree(GetProcessHeap(), 0, mem); ++ ++ return WINED3D_OK; ++} ++ ++static void surface_multisample_resolve(struct wined3d_surface *surface) ++{ ++ RECT rect = {0, 0, surface->resource.width, surface->resource.height}; ++ ++ if (!(surface->locations & WINED3D_LOCATION_RB_MULTISAMPLE)) ++ ERR("Trying to resolve multisampled surface %p, but location WINED3D_LOCATION_RB_MULTISAMPLE not current.\n", ++ surface); ++ ++ surface_blt_fbo(surface->resource.device, WINED3D_TEXF_POINT, ++ surface, WINED3D_LOCATION_RB_MULTISAMPLE, &rect, surface, WINED3D_LOCATION_RB_RESOLVED, &rect); ++} ++ ++HRESULT surface_load_location(struct wined3d_surface *surface, DWORD location) ++{ ++ struct wined3d_device *device = surface->resource.device; ++ const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; ++#endif /* STAGING_CSMT */ + HRESULT hr; + + TRACE("surface %p, location %s.\n", surface, wined3d_debug_location(location)); +@@ -3983,6 +5123,7 @@ + if (surface->resource.usage & WINED3DUSAGE_DEPTHSTENCIL) + { + if (location == WINED3D_LOCATION_TEXTURE_RGB ++#if defined(STAGING_CSMT) + && surface->resource.locations & (WINED3D_LOCATION_DRAWABLE | WINED3D_LOCATION_DISCARDED)) + { + surface_load_ds_location(surface, context, location); +@@ -4002,11 +5143,53 @@ + } + } + +- if (!surface->resource.locations) ++ if (!surface->resource.locations) ++ { ++ ERR("Surface %p does not have any up to date location.\n", surface); ++ surface->flags |= SFLAG_LOST; ++ return; ++#else /* STAGING_CSMT */ ++ && surface->locations & (WINED3D_LOCATION_DRAWABLE | WINED3D_LOCATION_DISCARDED)) ++ { ++ struct wined3d_context *context = context_acquire(device, NULL); ++ surface_load_ds_location(surface, context, location); ++ context_release(context); ++ return WINED3D_OK; ++ } ++ else if (location & surface->locations ++ && surface->container->resource.draw_binding != WINED3D_LOCATION_DRAWABLE) ++ { ++ /* Already up to date, nothing to do. */ ++ return WINED3D_OK; ++ } ++ else ++ { ++ FIXME("Unimplemented copy from %s to %s for depth/stencil buffers.\n", ++ wined3d_debug_location(surface->locations), wined3d_debug_location(location)); ++ return WINED3DERR_INVALIDCALL; ++ } ++ } ++ ++ if (surface->locations & location) ++ { ++ TRACE("Location already up to date.\n"); ++ return WINED3D_OK; ++ } ++ ++ if (WARN_ON(d3d_surface)) ++ { ++ DWORD required_access = resource_access_from_location(location); ++ if ((surface->resource.access_flags & required_access) != required_access) ++ WARN("Operation requires %#x access, but surface only has %#x.\n", ++ required_access, surface->resource.access_flags); ++ } ++ ++ if (!surface->locations) + { + ERR("Surface %p does not have any up to date location.\n", surface); + surface->flags |= SFLAG_LOST; +- return; ++ return WINED3DERR_DEVICELOST; ++#endif /* STAGING_CSMT */ + } + + switch (location) +@@ -4015,6 +5198,7 @@ + case WINED3D_LOCATION_USER_MEMORY: + case WINED3D_LOCATION_SYSMEM: + case WINED3D_LOCATION_BUFFER: ++#if defined(STAGING_CSMT) + surface_load_sysmem(surface, context, location); + break; + +@@ -4032,6 +5216,24 @@ + if (FAILED(hr = surface_load_texture(surface, context, + location == WINED3D_LOCATION_TEXTURE_SRGB))) + return; ++#else /* STAGING_CSMT */ ++ surface_load_sysmem(surface, gl_info, location); ++ break; ++ ++ case WINED3D_LOCATION_DRAWABLE: ++ if (FAILED(hr = surface_load_drawable(surface, gl_info))) ++ return hr; ++ break; ++ ++ case WINED3D_LOCATION_RB_RESOLVED: ++ surface_multisample_resolve(surface); ++ break; ++ ++ case WINED3D_LOCATION_TEXTURE_RGB: ++ case WINED3D_LOCATION_TEXTURE_SRGB: ++ if (FAILED(hr = surface_load_texture(surface, gl_info, location == WINED3D_LOCATION_TEXTURE_SRGB))) ++ return hr; ++#endif /* STAGING_CSMT */ + break; + + default: +@@ -4039,12 +5241,21 @@ + break; + } + ++#if defined(STAGING_CSMT) + wined3d_resource_validate_location(&surface->resource, location); + + if (location != WINED3D_LOCATION_SYSMEM && (surface->resource.locations & WINED3D_LOCATION_SYSMEM)) + surface_evict_sysmem(surface); + + return; ++#else /* STAGING_CSMT */ ++ surface_validate_location(surface, location); ++ ++ if (location != WINED3D_LOCATION_SYSMEM && (surface->locations & WINED3D_LOCATION_SYSMEM)) ++ surface_evict_sysmem(surface); ++ ++ return WINED3D_OK; ++#endif /* STAGING_CSMT */ + } + + static HRESULT ffp_blit_alloc(struct wined3d_device *device) { return WINED3D_OK; } +@@ -4138,6 +5349,7 @@ + const RECT *dst_rect, const struct wined3d_color *color) + { + const RECT draw_rect = {0, 0, dst_surface->resource.width, dst_surface->resource.height}; ++#if defined(STAGING_CSMT) + struct wined3d_rendertarget_view view, *view_ptr = &view; + struct wined3d_fb_state fb = {&view_ptr, NULL, 1}; + struct wined3d_texture *texture = dst_surface->container; +@@ -4158,6 +5370,21 @@ + view.sub_resource_idx = dst_surface->texture_layer * texture->level_count + dst_surface->texture_level; + + device_clear_render_targets(device, 1, &fb, 1, dst_rect, &draw_rect, WINED3DCLEAR_TARGET, color, 0.0f, 0); ++#else /* STAGING_CSMT */ ++ struct wined3d_rendertarget_view *view; ++ struct wined3d_fb_state fb = {&view, NULL}; ++ HRESULT hr; ++ ++ if (FAILED(hr = wined3d_rendertarget_view_create_from_surface(dst_surface, ++ NULL, &wined3d_null_parent_ops, &view))) ++ { ++ ERR("Failed to create rendertarget view, hr %#x.\n", hr); ++ return hr; ++ } ++ ++ device_clear_render_targets(device, 1, &fb, 1, dst_rect, &draw_rect, WINED3DCLEAR_TARGET, color, 0.0f, 0); ++ wined3d_rendertarget_view_decref(view); ++#endif /* STAGING_CSMT */ + + return WINED3D_OK; + } +@@ -4166,6 +5393,7 @@ + const RECT *dst_rect, float depth) + { + const RECT draw_rect = {0, 0, dst_surface->resource.width, dst_surface->resource.height}; ++#if defined(STAGING_CSMT) + struct wined3d_rendertarget_view view; + struct wined3d_fb_state fb = {NULL, &view}; + struct wined3d_texture *texture = dst_surface->container; +@@ -4181,6 +5409,20 @@ + view.sub_resource_idx = dst_surface->texture_layer * texture->level_count + dst_surface->texture_level; + + device_clear_render_targets(device, 0, &fb, 1, dst_rect, &draw_rect, WINED3DCLEAR_ZBUFFER, 0, depth, 0); ++#else /* STAGING_CSMT */ ++ struct wined3d_fb_state fb = {NULL, NULL}; ++ HRESULT hr; ++ ++ if (FAILED(hr = wined3d_rendertarget_view_create_from_surface(dst_surface, ++ NULL, &wined3d_null_parent_ops, &fb.depth_stencil))) ++ { ++ ERR("Failed to create rendertarget view, hr %#x.\n", hr); ++ return hr; ++ } ++ ++ device_clear_render_targets(device, 0, &fb, 1, dst_rect, &draw_rect, WINED3DCLEAR_ZBUFFER, 0, depth, 0); ++ wined3d_rendertarget_view_decref(fb.depth_stencil); ++#endif /* STAGING_CSMT */ + + return WINED3D_OK; + } +@@ -4338,6 +5580,7 @@ + int bpp, srcheight, srcwidth, dstheight, dstwidth, width; + const struct wined3d_format *src_format, *dst_format; + struct wined3d_texture *src_texture = NULL; ++#if defined(STAGING_CSMT) + void *src_data = NULL, *dst_data = NULL; + UINT src_row_pitch, src_slice_pitch, dst_row_pitch, dst_slice_pitch; + const BYTE *sbase = NULL; +@@ -4368,6 +5611,23 @@ + wined3d_resource_get_pitch(&dst_surface->resource, &dst_row_pitch, &dst_slice_pitch); + src_data = dst_data; + src_row_pitch = dst_row_pitch; ++#else /* STAGING_CSMT */ ++ struct wined3d_map_desc dst_map, src_map; ++ const BYTE *sbase = NULL; ++ HRESULT hr = WINED3D_OK; ++ const BYTE *sbuf; ++ BYTE *dbuf; ++ int x, y; ++ ++ TRACE("dst_surface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p, filter %s.\n", ++ dst_surface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), ++ flags, fx, debug_d3dtexturefiltertype(filter)); ++ ++ if (src_surface == dst_surface) ++ { ++ wined3d_surface_map(dst_surface, &dst_map, NULL, 0); ++ src_map = dst_map; ++#endif /* STAGING_CSMT */ + src_format = dst_surface->resource.format; + dst_format = src_format; + } +@@ -4376,12 +5636,14 @@ + dst_format = dst_surface->resource.format; + if (src_surface) + { ++#if defined(STAGING_CSMT) + if (!wined3d_resource_prepare_map_memory(&src_surface->resource, context)) + { + hr = E_OUTOFMEMORY; + goto error; + } + ++#endif /* STAGING_CSMT */ + if (dst_surface->resource.format->id != src_surface->resource.format->id) + { + if (!(src_texture = surface_convert_format(src_surface, dst_format->id))) +@@ -4392,9 +5654,13 @@ + } + src_surface = surface_from_resource(wined3d_texture_get_sub_resource(src_texture, 0)); + } ++#if defined(STAGING_CSMT) + wined3d_resource_load_location(&src_surface->resource, context, src_surface->resource.map_binding); + wined3d_resource_get_pitch(&src_surface->resource, &src_row_pitch, &src_slice_pitch); + src_data = wined3d_resource_get_map_ptr(&src_surface->resource, context, 0); ++#else /* STAGING_CSMT */ ++ wined3d_surface_map(src_surface, &src_map, NULL, WINED3D_MAP_READONLY); ++#endif /* STAGING_CSMT */ + src_format = src_surface->resource.format; + } + else +@@ -4402,8 +5668,12 @@ + src_format = dst_format; + } + ++#if defined(STAGING_CSMT) + wined3d_resource_get_pitch(&dst_surface->resource, &dst_row_pitch, &dst_slice_pitch); + dst_data = wined3d_resource_get_map_ptr(&dst_surface->resource, context, 0); ++#else /* STAGING_CSMT */ ++ wined3d_surface_map(dst_surface, &dst_map, dst_rect, 0); ++#endif /* STAGING_CSMT */ + } + + bpp = dst_surface->resource.format->byte_count; +@@ -4414,12 +5684,24 @@ + width = (dst_rect->right - dst_rect->left) * bpp; + + if (src_surface) ++#if defined(STAGING_CSMT) + sbase = (BYTE *)src_data + + ((src_rect->top / src_format->block_height) * src_row_pitch) + + ((src_rect->left / src_format->block_width) * src_format->block_byte_count); + dbuf = (BYTE *)dst_data + + ((dst_rect->top / dst_format->block_height) * dst_row_pitch) + + ((dst_rect->left / dst_format->block_width) * dst_format->block_byte_count); ++#else /* STAGING_CSMT */ ++ sbase = (BYTE *)src_map.data ++ + ((src_rect->top / src_format->block_height) * src_map.row_pitch) ++ + ((src_rect->left / src_format->block_width) * src_format->block_byte_count); ++ if (src_surface != dst_surface) ++ dbuf = dst_map.data; ++ else ++ dbuf = (BYTE *)dst_map.data ++ + ((dst_rect->top / dst_format->block_height) * dst_map.row_pitch) ++ + ((dst_rect->left / dst_format->block_width) * dst_format->block_byte_count); ++#endif /* STAGING_CSMT */ + + if (src_format->flags & dst_format->flags & WINED3DFMT_FLAG_BLOCKS) + { +@@ -4454,7 +5736,11 @@ + } + + hr = surface_cpu_blt_compressed(sbase, dbuf, ++#if defined(STAGING_CSMT) + src_row_pitch, dst_row_pitch, dstwidth, dstheight, ++#else /* STAGING_CSMT */ ++ src_map.row_pitch, dst_map.row_pitch, dstwidth, dstheight, ++#endif /* STAGING_CSMT */ + src_format, flags, fx); + goto release; + } +@@ -4462,7 +5748,11 @@ + /* First, all the 'source-less' blits */ + if (flags & WINEDDBLT_COLORFILL) + { ++#if defined(STAGING_CSMT) + hr = _Blt_ColorFill(dbuf, dstwidth, dstheight, bpp, dst_row_pitch, fx->u5.dwFillColor); ++#else /* STAGING_CSMT */ ++ hr = _Blt_ColorFill(dbuf, dstwidth, dstheight, bpp, dst_map.row_pitch, fx->u5.dwFillColor); ++#endif /* STAGING_CSMT */ + flags &= ~WINEDDBLT_COLORFILL; + } + +@@ -4476,12 +5766,21 @@ + switch (fx->dwROP) + { + case BLACKNESS: ++#if defined(STAGING_CSMT) + hr = _Blt_ColorFill(dbuf, dstwidth, dstheight, bpp, dst_row_pitch, 0); + break; + case 0xaa0029: /* No-op */ + break; + case WHITENESS: + hr = _Blt_ColorFill(dbuf, dstwidth, dstheight, bpp, dst_row_pitch, ~0U); ++#else /* STAGING_CSMT */ ++ hr = _Blt_ColorFill(dbuf, dstwidth, dstheight, bpp, dst_map.row_pitch, 0); ++ break; ++ case 0xaa0029: /* No-op */ ++ break; ++ case WHITENESS: ++ hr = _Blt_ColorFill(dbuf, dstwidth, dstheight, bpp, dst_map.row_pitch, ~0U); ++#endif /* STAGING_CSMT */ + break; + case SRCCOPY: /* Well, we do that below? */ + break; +@@ -4532,6 +5831,7 @@ + for (y = 0; y < dstheight; ++y) + { + memcpy(dbuf, sbuf, width); ++#if defined(STAGING_CSMT) + sbuf += src_row_pitch; + dbuf += dst_row_pitch; + } +@@ -4545,6 +5845,21 @@ + { + sbuf -= src_row_pitch; + dbuf -= dst_row_pitch; ++#else /* STAGING_CSMT */ ++ sbuf += src_map.row_pitch; ++ dbuf += dst_map.row_pitch; ++ } ++ } ++ else if (dst_rect->top > src_rect->top) ++ { ++ /* Copy from bottom upwards. */ ++ sbuf += src_map.row_pitch * dstheight; ++ dbuf += dst_map.row_pitch * dstheight; ++ for (y = 0; y < dstheight; ++y) ++ { ++ sbuf -= src_map.row_pitch; ++ dbuf -= dst_map.row_pitch; ++#endif /* STAGING_CSMT */ + memcpy(dbuf, sbuf, width); + } + } +@@ -4554,8 +5869,13 @@ + for (y = 0; y < dstheight; ++y) + { + memmove(dbuf, sbuf, width); ++#if defined(STAGING_CSMT) + sbuf += src_row_pitch; + dbuf += dst_row_pitch; ++#else /* STAGING_CSMT */ ++ sbuf += src_map.row_pitch; ++ dbuf += dst_map.row_pitch; ++#endif /* STAGING_CSMT */ + } + } + } +@@ -4564,9 +5884,15 @@ + /* Stretching in y direction only. */ + for (y = sy = 0; y < dstheight; ++y, sy += yinc) + { ++#if defined(STAGING_CSMT) + sbuf = sbase + (sy >> 16) * src_row_pitch; + memcpy(dbuf, sbuf, width); + dbuf += dst_row_pitch; ++#else /* STAGING_CSMT */ ++ sbuf = sbase + (sy >> 16) * src_map.row_pitch; ++ memcpy(dbuf, sbuf, width); ++ dbuf += dst_map.row_pitch; ++#endif /* STAGING_CSMT */ + } + } + } +@@ -4576,6 +5902,7 @@ + int last_sy = -1; + for (y = sy = 0; y < dstheight; ++y, sy += yinc) + { ++#if defined(STAGING_CSMT) + sbuf = sbase + (sy >> 16) * src_row_pitch; + + if ((sy >> 16) == (last_sy >> 16)) +@@ -4583,6 +5910,15 @@ + /* This source row is the same as last source row - + * Copy the already stretched row. */ + memcpy(dbuf, dbuf - dst_row_pitch, width); ++#else /* STAGING_CSMT */ ++ sbuf = sbase + (sy >> 16) * src_map.row_pitch; ++ ++ if ((sy >> 16) == (last_sy >> 16)) ++ { ++ /* This source row is the same as last source row - ++ * Copy the already stretched row. */ ++ memcpy(dbuf, dbuf - dst_map.row_pitch, width); ++#endif /* STAGING_CSMT */ + } + else + { +@@ -4629,6 +5965,7 @@ + } + #undef STRETCH_ROW + } ++#if defined(STAGING_CSMT) + dbuf += dst_row_pitch; + last_sy = sy; + } +@@ -4637,6 +5974,16 @@ + else + { + LONG dstyinc = dst_row_pitch, dstxinc = bpp; ++#else /* STAGING_CSMT */ ++ dbuf += dst_map.row_pitch; ++ last_sy = sy; ++ } ++ } ++ } ++ else ++ { ++ LONG dstyinc = dst_map.row_pitch, dstxinc = bpp; ++#endif /* STAGING_CSMT */ + DWORD keylow = 0xffffffff, keyhigh = 0, keymask = 0xffffffff; + DWORD destkeylow = 0x0, destkeyhigh = 0xffffffff, destkeymask = 0xffffffff; + if (flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYDEST | WINEDDBLT_KEYSRCOVERRIDE | WINEDDBLT_KEYDESTOVERRIDE)) +@@ -4686,7 +6033,11 @@ + LONG tmpxy; + dTopLeft = dbuf; + dTopRight = dbuf + ((dstwidth - 1) * bpp); ++#if defined(STAGING_CSMT) + dBottomLeft = dTopLeft + ((dstheight - 1) * dst_row_pitch); ++#else /* STAGING_CSMT */ ++ dBottomLeft = dTopLeft + ((dstheight - 1) * dst_map.row_pitch); ++#endif /* STAGING_CSMT */ + dBottomRight = dBottomLeft + ((dstwidth - 1) * bpp); + + if (fx->dwDDFX & WINEDDBLTFX_ARITHSTRETCHY) +@@ -4763,6 +6114,7 @@ + flags &= ~(WINEDDBLT_DDFX); + } + ++#if defined(STAGING_CSMT) + #define COPY_COLORKEY_FX(type) \ + do { \ + const type *s; \ +@@ -4784,6 +6136,29 @@ + d = (type *)(((BYTE *)d) + dstyinc); \ + } \ + } while(0) ++#else /* STAGING_CSMT */ ++#define COPY_COLORKEY_FX(type) \ ++do { \ ++ const type *s; \ ++ type *d = (type *)dbuf, *dx, tmp; \ ++ for (y = sy = 0; y < dstheight; ++y, sy += yinc) \ ++ { \ ++ s = (const type *)(sbase + (sy >> 16) * src_map.row_pitch); \ ++ dx = d; \ ++ for (x = sx = 0; x < dstwidth; ++x, sx += xinc) \ ++ { \ ++ tmp = s[sx >> 16]; \ ++ if (((tmp & keymask) < keylow || (tmp & keymask) > keyhigh) \ ++ && ((dx[0] & destkeymask) >= destkeylow && (dx[0] & destkeymask) <= destkeyhigh)) \ ++ { \ ++ dx[0] = tmp; \ ++ } \ ++ dx = (type *)(((BYTE *)dx) + dstxinc); \ ++ } \ ++ d = (type *)(((BYTE *)d) + dstyinc); \ ++ } \ ++} while(0) ++#endif /* STAGING_CSMT */ + + switch (bpp) + { +@@ -4802,7 +6177,11 @@ + BYTE *d = dbuf, *dx; + for (y = sy = 0; y < dstheight; ++y, sy += yinc) + { ++#if defined(STAGING_CSMT) + sbuf = sbase + (sy >> 16) * src_row_pitch; ++#else /* STAGING_CSMT */ ++ sbuf = sbase + (sy >> 16) * src_map.row_pitch; ++#endif /* STAGING_CSMT */ + dx = d; + for (x = sx = 0; x < dstwidth; ++x, sx+= xinc) + { +@@ -4833,10 +6212,12 @@ + } + } + ++#if defined(STAGING_CSMT) + wined3d_resource_invalidate_location(&dst_surface->resource, ~dst_surface->resource.map_binding); + if (dst_surface->container) + wined3d_texture_set_dirty(dst_surface->container); + ++#endif /* STAGING_CSMT */ + error: + if (flags && FIXME_ON(d3d_surface)) + { +@@ -4844,6 +6225,7 @@ + } + + release: ++#if defined(STAGING_CSMT) + if (dst_data) + { + wined3d_resource_release_map_ptr(&dst_surface->resource, context); +@@ -4862,6 +6244,14 @@ + wined3d_texture_decref(src_texture); + if (context) + context_release(context); ++#else /* STAGING_CSMT */ ++ wined3d_surface_unmap(dst_surface); ++ if (src_surface && src_surface != dst_surface) ++ wined3d_surface_unmap(src_surface); ++ /* Release the converted surface, if any. */ ++ if (src_texture) ++ wined3d_texture_decref(src_texture); ++#endif /* STAGING_CSMT */ + + return hr; + } +@@ -4896,6 +6286,7 @@ + cpu_blit_depth_fill, + }; + ++#if defined(STAGING_CSMT) + void surface_blt_ugly(struct wined3d_surface *dst_surface, const RECT *dst_rect, + struct wined3d_surface *src_surface, const RECT *src_rect, DWORD flags, + const WINEDDBLTFX *fx, enum wined3d_texture_filter_type filter) +@@ -4903,6 +6294,16 @@ + struct wined3d_swapchain *src_swapchain, *dst_swapchain; + struct wined3d_device *device = dst_surface->resource.device; + DWORD src_ds_flags, dst_ds_flags; ++#else /* STAGING_CSMT */ ++HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const RECT *dst_rect_in, ++ struct wined3d_surface *src_surface, const RECT *src_rect_in, DWORD flags, ++ const WINEDDBLTFX *fx, enum wined3d_texture_filter_type filter) ++{ ++ struct wined3d_swapchain *src_swapchain, *dst_swapchain; ++ struct wined3d_device *device = dst_surface->resource.device; ++ DWORD src_ds_flags, dst_ds_flags; ++ RECT src_rect, dst_rect; ++#endif /* STAGING_CSMT */ + BOOL scale, convert; + + static const DWORD simple_blit = WINEDDBLT_ASYNC +@@ -4911,6 +6312,106 @@ + | WINEDDBLT_DEPTHFILL + | WINEDDBLT_DONOTWAIT; + ++#if !defined(STAGING_CSMT) ++ TRACE("dst_surface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p, filter %s.\n", ++ dst_surface, wine_dbgstr_rect(dst_rect_in), src_surface, wine_dbgstr_rect(src_rect_in), ++ flags, fx, debug_d3dtexturefiltertype(filter)); ++ TRACE("Usage is %s.\n", debug_d3dusage(dst_surface->resource.usage)); ++ ++ if (fx) ++ { ++ TRACE("dwSize %#x.\n", fx->dwSize); ++ TRACE("dwDDFX %#x.\n", fx->dwDDFX); ++ TRACE("dwROP %#x.\n", fx->dwROP); ++ TRACE("dwDDROP %#x.\n", fx->dwDDROP); ++ TRACE("dwRotationAngle %#x.\n", fx->dwRotationAngle); ++ TRACE("dwZBufferOpCode %#x.\n", fx->dwZBufferOpCode); ++ TRACE("dwZBufferLow %#x.\n", fx->dwZBufferLow); ++ TRACE("dwZBufferHigh %#x.\n", fx->dwZBufferHigh); ++ TRACE("dwZBufferBaseDest %#x.\n", fx->dwZBufferBaseDest); ++ TRACE("dwZDestConstBitDepth %#x.\n", fx->dwZDestConstBitDepth); ++ TRACE("lpDDSZBufferDest %p.\n", fx->u1.lpDDSZBufferDest); ++ TRACE("dwZSrcConstBitDepth %#x.\n", fx->dwZSrcConstBitDepth); ++ TRACE("lpDDSZBufferSrc %p.\n", fx->u2.lpDDSZBufferSrc); ++ TRACE("dwAlphaEdgeBlendBitDepth %#x.\n", fx->dwAlphaEdgeBlendBitDepth); ++ TRACE("dwAlphaEdgeBlend %#x.\n", fx->dwAlphaEdgeBlend); ++ TRACE("dwReserved %#x.\n", fx->dwReserved); ++ TRACE("dwAlphaDestConstBitDepth %#x.\n", fx->dwAlphaDestConstBitDepth); ++ TRACE("lpDDSAlphaDest %p.\n", fx->u3.lpDDSAlphaDest); ++ TRACE("dwAlphaSrcConstBitDepth %#x.\n", fx->dwAlphaSrcConstBitDepth); ++ TRACE("lpDDSAlphaSrc %p.\n", fx->u4.lpDDSAlphaSrc); ++ TRACE("lpDDSPattern %p.\n", fx->u5.lpDDSPattern); ++ TRACE("ddckDestColorkey {%#x, %#x}.\n", ++ fx->ddckDestColorkey.color_space_low_value, ++ fx->ddckDestColorkey.color_space_high_value); ++ TRACE("ddckSrcColorkey {%#x, %#x}.\n", ++ fx->ddckSrcColorkey.color_space_low_value, ++ fx->ddckSrcColorkey.color_space_high_value); ++ } ++ ++ if (dst_surface->resource.map_count || (src_surface && src_surface->resource.map_count)) ++ { ++ WARN("Surface is busy, returning WINEDDERR_SURFACEBUSY.\n"); ++ return WINEDDERR_SURFACEBUSY; ++ } ++ ++ surface_get_rect(dst_surface, dst_rect_in, &dst_rect); ++ ++ if (dst_rect.left >= dst_rect.right || dst_rect.top >= dst_rect.bottom ++ || dst_rect.left > dst_surface->resource.width || dst_rect.left < 0 ++ || dst_rect.top > dst_surface->resource.height || dst_rect.top < 0 ++ || dst_rect.right > dst_surface->resource.width || dst_rect.right < 0 ++ || dst_rect.bottom > dst_surface->resource.height || dst_rect.bottom < 0) ++ { ++ WARN("The application gave us a bad destination rectangle.\n"); ++ return WINEDDERR_INVALIDRECT; ++ } ++ ++ if (src_surface) ++ { ++ surface_get_rect(src_surface, src_rect_in, &src_rect); ++ ++ if (src_rect.left >= src_rect.right || src_rect.top >= src_rect.bottom ++ || src_rect.left > src_surface->resource.width || src_rect.left < 0 ++ || src_rect.top > src_surface->resource.height || src_rect.top < 0 ++ || src_rect.right > src_surface->resource.width || src_rect.right < 0 ++ || src_rect.bottom > src_surface->resource.height || src_rect.bottom < 0) ++ { ++ WARN("Application gave us bad source rectangle for Blt.\n"); ++ return WINEDDERR_INVALIDRECT; ++ } ++ } ++ else ++ { ++ memset(&src_rect, 0, sizeof(src_rect)); ++ } ++ ++ if (!fx || !(fx->dwDDFX)) ++ flags &= ~WINEDDBLT_DDFX; ++ ++ if (flags & WINEDDBLT_WAIT) ++ flags &= ~WINEDDBLT_WAIT; ++ ++ if (flags & WINEDDBLT_ASYNC) ++ { ++ static unsigned int once; ++ ++ if (!once++) ++ FIXME("Can't handle WINEDDBLT_ASYNC flag.\n"); ++ flags &= ~WINEDDBLT_ASYNC; ++ } ++ ++ /* WINEDDBLT_DONOTWAIT appeared in DX7. */ ++ if (flags & WINEDDBLT_DONOTWAIT) ++ { ++ static unsigned int once; ++ ++ if (!once++) ++ FIXME("Can't handle WINEDDBLT_DONOTWAIT flag.\n"); ++ flags &= ~WINEDDBLT_DONOTWAIT; ++ } ++ ++#endif /* STAGING_CSMT */ + if (!device->d3d_initialized) + { + WARN("D3D not initialized, using fallback.\n"); +@@ -4953,8 +6454,13 @@ + } + + scale = src_surface ++#if defined(STAGING_CSMT) + && (src_rect->right - src_rect->left != dst_rect->right - dst_rect->left + || src_rect->bottom - src_rect->top != dst_rect->bottom - dst_rect->top); ++#else /* STAGING_CSMT */ ++ && (src_rect.right - src_rect.left != dst_rect.right - dst_rect.left ++ || src_rect.bottom - src_rect.top != dst_rect.bottom - dst_rect.top); ++#endif /* STAGING_CSMT */ + convert = src_surface && src_surface->resource.format->id != dst_surface->resource.format->id; + + dst_ds_flags = dst_surface->resource.format->flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL); +@@ -4972,6 +6478,7 @@ + TRACE("Depth fill.\n"); + + if (!surface_convert_depth_to_float(dst_surface, fx->u5.dwFillDepth, &depth)) ++#if defined(STAGING_CSMT) + return; + + if (SUCCEEDED(wined3d_surface_depth_fill(dst_surface, dst_rect, depth))) +@@ -4990,6 +6497,32 @@ + * implement those in the CPU blitter at the moment. */ + if ((dst_surface->resource.locations & dst_surface->resource.map_binding) + && (!src_surface || (src_surface->resource.locations & src_surface->resource.map_binding))) ++#else /* STAGING_CSMT */ ++ return WINED3DERR_INVALIDCALL; ++ ++ if (SUCCEEDED(wined3d_surface_depth_fill(dst_surface, &dst_rect, depth))) ++ return WINED3D_OK; ++ } ++ else ++ { ++ if (src_ds_flags != dst_ds_flags) ++ { ++ WARN("Rejecting depth / stencil blit between incompatible formats.\n"); ++ return WINED3DERR_INVALIDCALL; ++ } ++ ++ if (SUCCEEDED(wined3d_surface_depth_blt(src_surface, src_surface->container->resource.draw_binding, ++ &src_rect, dst_surface, dst_surface->container->resource.draw_binding, &dst_rect))) ++ return WINED3D_OK; ++ } ++ } ++ else ++ { ++ /* In principle this would apply to depth blits as well, but we don't ++ * implement those in the CPU blitter at the moment. */ ++ if ((dst_surface->locations & dst_surface->resource.map_binding) ++ && (!src_surface || (src_surface->locations & src_surface->resource.map_binding))) ++#endif /* STAGING_CSMT */ + { + if (scale) + TRACE("Not doing sysmem blit because of scaling.\n"); +@@ -5008,6 +6541,7 @@ + if (!surface_convert_color_to_float(dst_surface, fx->u5.dwFillColor, &color)) + goto fallback; + ++#if defined(STAGING_CSMT) + if (SUCCEEDED(surface_color_fill(dst_surface, dst_rect, &color))) + return; + } +@@ -5018,6 +6552,18 @@ + /* Upload */ + if ((src_surface->resource.locations & WINED3D_LOCATION_SYSMEM) + && !(dst_surface->resource.locations & WINED3D_LOCATION_SYSMEM)) ++#else /* STAGING_CSMT */ ++ if (SUCCEEDED(surface_color_fill(dst_surface, &dst_rect, &color))) ++ return WINED3D_OK; ++ } ++ else ++ { ++ TRACE("Color blit.\n"); ++ ++ /* Upload */ ++ if ((src_surface->locations & WINED3D_LOCATION_SYSMEM) ++ && !(dst_surface->locations & WINED3D_LOCATION_SYSMEM)) ++#endif /* STAGING_CSMT */ + { + if (scale) + TRACE("Not doing upload because of scaling.\n"); +@@ -5025,6 +6571,7 @@ + TRACE("Not doing upload because of format conversion.\n"); + else + { ++#if defined(STAGING_CSMT) + POINT dst_point = {dst_rect->left, dst_rect->top}; + + if (SUCCEEDED(surface_upload_from_surface(dst_surface, &dst_point, src_surface, src_rect))) +@@ -5037,6 +6584,15 @@ + context_release(context); + } + return; ++#else /* STAGING_CSMT */ ++ POINT dst_point = {dst_rect.left, dst_rect.top}; ++ ++ if (SUCCEEDED(surface_upload_from_surface(dst_surface, &dst_point, src_surface, &src_rect))) ++ { ++ if (!wined3d_resource_is_offscreen(&dst_surface->container->resource)) ++ surface_load_location(dst_surface, dst_surface->container->resource.draw_binding); ++ return WINED3D_OK; ++#endif /* STAGING_CSMT */ + } + } + } +@@ -5061,6 +6617,7 @@ + wined3d_swapchain_present(dst_swapchain, NULL, NULL, dst_swapchain->win_handle, NULL, 0); + dst_swapchain->desc.swap_effect = swap_effect; + ++#if defined(STAGING_CSMT) + return; + } + +@@ -5257,6 +6814,50 @@ + wined3d_surface_location_invalidated, + wined3d_surface_load_location, + }; ++#else /* STAGING_CSMT */ ++ return WINED3D_OK; ++ } ++ ++ if (fbo_blit_supported(&device->adapter->gl_info, WINED3D_BLIT_OP_COLOR_BLIT, ++ &src_rect, src_surface->resource.usage, src_surface->resource.pool, src_surface->resource.format, ++ &dst_rect, dst_surface->resource.usage, dst_surface->resource.pool, dst_surface->resource.format)) ++ { ++ TRACE("Using FBO blit.\n"); ++ ++ surface_blt_fbo(device, filter, ++ src_surface, src_surface->container->resource.draw_binding, &src_rect, ++ dst_surface, dst_surface->container->resource.draw_binding, &dst_rect); ++ surface_validate_location(dst_surface, dst_surface->container->resource.draw_binding); ++ surface_invalidate_location(dst_surface, ~dst_surface->container->resource.draw_binding); ++ ++ return WINED3D_OK; ++ } ++ ++ if (arbfp_blit.blit_supported(&device->adapter->gl_info, WINED3D_BLIT_OP_COLOR_BLIT, ++ &src_rect, src_surface->resource.usage, src_surface->resource.pool, src_surface->resource.format, ++ &dst_rect, dst_surface->resource.usage, dst_surface->resource.pool, dst_surface->resource.format)) ++ { ++ TRACE("Using arbfp blit.\n"); ++ ++ if (SUCCEEDED(arbfp_blit_surface(device, filter, src_surface, &src_rect, dst_surface, &dst_rect))) ++ return WINED3D_OK; ++ } ++ } ++ } ++ ++fallback: ++ /* Special cases for render targets. */ ++ if (SUCCEEDED(surface_blt_special(dst_surface, &dst_rect, src_surface, &src_rect, flags, fx, filter))) ++ return WINED3D_OK; ++ ++cpu: ++ ++ /* For the rest call the X11 surface implementation. For render targets ++ * this should be implemented OpenGL accelerated in surface_blt_special(), ++ * other blits are rather rare. */ ++ return surface_cpu_blt(dst_surface, &dst_rect, src_surface, &src_rect, flags, fx, filter); ++} ++#endif /* STAGING_CSMT */ + + static HRESULT surface_init(struct wined3d_surface *surface, struct wined3d_texture *container, + const struct wined3d_resource_desc *desc, GLenum target, unsigned int level, unsigned int layer, DWORD flags) +@@ -5324,7 +6925,11 @@ + } + + surface->container = container; ++#if defined(STAGING_CSMT) + wined3d_resource_validate_location(&surface->resource, WINED3D_LOCATION_SYSMEM); ++#else /* STAGING_CSMT */ ++ surface_validate_location(surface, WINED3D_LOCATION_SYSMEM); ++#endif /* STAGING_CSMT */ + list_init(&surface->renderbuffers); + list_init(&surface->overlays); + +@@ -5356,9 +6961,14 @@ + if (surface->resource.map_binding == WINED3D_LOCATION_DIB) + { + wined3d_resource_free_sysmem(&surface->resource); ++#if defined(STAGING_CSMT) + surface->resource.map_heap_memory = NULL; + wined3d_resource_validate_location(&surface->resource, WINED3D_LOCATION_DIB); + wined3d_resource_invalidate_location(&surface->resource, WINED3D_LOCATION_SYSMEM); ++#else /* STAGING_CSMT */ ++ surface_validate_location(surface, WINED3D_LOCATION_DIB); ++ surface_invalidate_location(surface, WINED3D_LOCATION_SYSMEM); ++#endif /* STAGING_CSMT */ + } + + return hr; +@@ -5385,7 +6995,11 @@ + if (FAILED(hr = surface_init(object, container, desc, target, level, layer, flags))) + { + WARN("Failed to initialize surface, returning %#x.\n", hr); ++#if defined(STAGING_CSMT) + /* The command stream takes care of freeing the memory. */ ++#else /* STAGING_CSMT */ ++ HeapFree(GetProcessHeap(), 0, object); ++#endif /* STAGING_CSMT */ + return hr; + } + +diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c +--- a/dlls/wined3d/shader.c ++++ b/dlls/wined3d/shader.c +@@ -1702,7 +1702,11 @@ + } + } + ++#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->signature_strings); + shader->device->shader_backend->shader_destroy(shader); +@@ -1957,10 +1961,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); ++#else /* STAGING_CSMT */ ++ shader_cleanup(shader); ++ shader->parent_ops->wined3d_object_destroyed(shader->parent); ++ HeapFree(GetProcessHeap(), 0, shader); ++#endif /* STAGING_CSMT */ + } + + return refcount; +@@ -2185,7 +2195,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) + const struct wined3d_format *rt_format = state->fb.render_targets[0]->format; ++#else /* STAGING_CSMT */ ++ const struct wined3d_format *rt_format = state->fb->render_targets[0]->format; ++#endif /* STAGING_CSMT */ + if (rt_format->flags & WINED3DFMT_FLAG_SRGB_WRITE) + { + static unsigned int warned = 0; +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 & 0xff00ff00); /* Alpha Green */ + *dst_color |= (src_color & 0x00ff0000) >> 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) + { ++#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(glBindBufferARB(This->buffer_type_hint, This->buffer_object)); ++ checkGLcall("glBindBufferARB"); ++ 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(glMapBufferARB(This->buffer_type_hint, GL_WRITE_ONLY_ARB)); ++ checkGLcall("glMapBufferARB"); ++ } ++ 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(glBufferSubDataARB(This->buffer_type_hint, start, len, (BYTE *)This->resource.heap_memory + start)); + checkGLcall("glBufferSubDataARB"); + } + } + + 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(glUnmapBufferARB(This->buffer_type_hint)); ++ checkGLcall("glUnmapBufferARB"); ++} ++ ++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); + } +@@ -1072,6 +1240,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); +@@ -1125,7 +1308,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) + { +@@ -1136,6 +1323,7 @@ + } + + GL_EXTCALL(glUnmapBufferARB(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) +@@ -1144,6 +1332,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 */ + } + } + +@@ -1157,6 +1357,7 @@ + return wined3d_buffer_decref(buffer_from_resource(resource)); + } + ++#if defined(STAGING_CSMT) + static void wined3d_buffer_location_invalidated(struct wined3d_resource *resource, DWORD location) + { + ERR("Not yet implemented.\n"); +@@ -1176,6 +1377,13 @@ + buffer_unload, + wined3d_buffer_location_invalidated, + wined3d_buffer_load_location, ++#else /* STAGING_CSMT */ ++static const struct wined3d_resource_ops buffer_resource_ops = ++{ ++ buffer_resource_incref, ++ buffer_resource_decref, ++ buffer_unload, ++#endif /* STAGING_CSMT */ + }; + + static HRESULT buffer_init(struct wined3d_buffer *buffer, struct wined3d_device *device, +@@ -1202,7 +1410,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); +@@ -1218,6 +1428,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). + * +@@ -1225,6 +1436,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"); +@@ -1270,9 +1490,11 @@ + } + buffer->maps_size = 1; + ++#if defined(STAGING_CSMT) + if (wined3d_settings.cs_multithreaded) + buffer->flags |= WINED3D_BUFFER_DOUBLEBUFFER; + ++#endif /* STAGING_CSMT */ + return WINED3D_OK; + } + +@@ -1378,6 +1600,7 @@ + + return WINED3D_OK; + } ++#if defined(STAGING_CSMT) + + void buffer_swap_mem(struct wined3d_buffer *buffer, BYTE *mem) + { +@@ -1385,3 +1608,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 +@@ -4731,9 +4731,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 +@@ -119,7 +119,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 + { +@@ -143,6 +145,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); +@@ -168,6 +171,7 @@ + resource->map_heap_memory = NULL; + } + ++#endif /* STAGING_CSMT */ + void resource_cleanup(struct wined3d_resource *resource) + { + const struct wined3d *d3d = resource->device->wined3d; +@@ -180,7 +184,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); + } +@@ -190,9 +198,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); + } +@@ -255,7 +265,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; + } +@@ -321,7 +335,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; +@@ -361,6 +379,7 @@ + resource->draw_binding = WINED3D_LOCATION_TEXTURE_RGB; + } + ++#if defined(STAGING_CSMT) + void wined3d_resource_validate_location(struct wined3d_resource *resource, DWORD location) + { + TRACE("Resource %p, setting %s.\n", resource, wined3d_debug_location(location)); +@@ -632,6 +651,7 @@ + } + } + ++#endif /* STAGING_CSMT */ + void CDECL wined3d_resource_get_pitch(const struct wined3d_resource *resource, UINT *row_pitch, + UINT *slice_pitch) + { +@@ -662,6 +682,7 @@ + + TRACE("Returning row pitch %u, slice pitch %u.\n", *row_pitch, *slice_pitch); + } ++#if defined(STAGING_CSMT) + + BOOL wined3d_resource_check_block_align(const struct wined3d_resource *resource, + const struct wined3d_box *box) +@@ -937,3 +958,4 @@ + + wined3d_resource_invalidate_location(resource, ~resource->map_binding); + } ++#endif /* STAGING_CSMT */ diff --git a/patches/wined3d-CSMT_Main/definition b/patches/wined3d-CSMT_Main/definition new file mode 100644 index 00000000..1770a0ab --- /dev/null +++ b/patches/wined3d-CSMT_Main/definition @@ -0,0 +1,3 @@ +Fixes: [11674] Support for CSMT (command stream) to increase graphic performance +Depends: wined3d-CSMT_Helper +IfDefined: STAGING_CSMT