swapchain.c 12 KB
Newer Older
1 2 3 4 5
/*
 * IDirect3DSwapChain9 implementation
 *
 * Copyright 2002-2003 Jason Edmeades
 *                     Raphael Junqueira
Oliver Stieber's avatar
Oliver Stieber committed
6
 * Copyright 2005 Oliver Stieber
7 8 9 10 11 12 13 14 15 16 17 18 19
 *
 * 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
20
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 22 23 24 25
 */

#include "config.h"
#include "d3d9_private.h"

Oliver Stieber's avatar
Oliver Stieber committed
26
WINE_DEFAULT_DEBUG_CHANNEL(d3d9);
27 28

/* IDirect3DSwapChain IUnknown parts follow: */
29
static HRESULT WINAPI IDirect3DSwapChain9Impl_QueryInterface(LPDIRECT3DSWAPCHAIN9 iface, REFIID riid, LPVOID* ppobj)
30
{
31
    IDirect3DSwapChain9Impl *This = (IDirect3DSwapChain9Impl *)iface;
32

Henri Verbeet's avatar
Henri Verbeet committed
33 34
    TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), ppobj);

35 36
    if (IsEqualGUID(riid, &IID_IUnknown)
        || IsEqualGUID(riid, &IID_IDirect3DSwapChain9)) {
37
        IDirect3DSwapChain9_AddRef(iface);
Oliver Stieber's avatar
Oliver Stieber committed
38
        *ppobj = This;
H. Verbeet's avatar
H. Verbeet committed
39
        return S_OK;
40 41 42
    }

    WARN("(%p)->(%s,%p),not found\n", This, debugstr_guid(riid), ppobj);
H. Verbeet's avatar
H. Verbeet committed
43
    *ppobj = NULL;
44 45 46
    return E_NOINTERFACE;
}

47
static ULONG WINAPI IDirect3DSwapChain9Impl_AddRef(LPDIRECT3DSWAPCHAIN9 iface) {
48
    IDirect3DSwapChain9Impl *This = (IDirect3DSwapChain9Impl *)iface;
49 50
    ULONG ref = InterlockedIncrement(&This->ref);

Henri Verbeet's avatar
Henri Verbeet committed
51
    TRACE("%p increasing refcount to %u.\n", iface, ref);
52

53 54 55 56 57
    if (ref == 1)
    {
        if (This->parentDevice)
            IDirect3DDevice9Ex_AddRef(This->parentDevice);

58
        wined3d_mutex_lock();
59
        wined3d_swapchain_incref(This->wined3d_swapchain);
60
        wined3d_mutex_unlock();
61
    }
62

63
    return ref;
64 65
}

66
static ULONG WINAPI IDirect3DSwapChain9Impl_Release(LPDIRECT3DSWAPCHAIN9 iface) {
67
    IDirect3DSwapChain9Impl *This = (IDirect3DSwapChain9Impl *)iface;
68 69
    ULONG ref = InterlockedDecrement(&This->ref);

Henri Verbeet's avatar
Henri Verbeet committed
70
    TRACE("%p decreasing refcount to %u.\n", iface, ref);
71

72
    if (ref == 0) {
73 74
        IDirect3DDevice9Ex *parentDevice = This->parentDevice;

75
        wined3d_mutex_lock();
76
        wined3d_swapchain_decref(This->wined3d_swapchain);
77
        wined3d_mutex_unlock();
78 79 80

        /* Release the device last, as it may cause the device to be destroyed. */
        if (parentDevice) IDirect3DDevice9Ex_Release(parentDevice);
81 82 83 84 85
    }
    return ref;
}

/* IDirect3DSwapChain9 parts follow: */
86
static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3DSwapChain9Impl_Present(LPDIRECT3DSWAPCHAIN9 iface, CONST RECT* pSourceRect, CONST RECT* pDestRect, HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion, DWORD dwFlags) {
87
    IDirect3DSwapChain9Impl *This = (IDirect3DSwapChain9Impl *)iface;
Henri Verbeet's avatar
Henri Verbeet committed
88 89
    HRESULT hr;

Henri Verbeet's avatar
Henri Verbeet committed
90 91
    TRACE("iface %p, src_rect %p, dst_rect %p, dst_window_override %p, dirty_region %p, flags %#x.\n",
            iface, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, dwFlags);
Henri Verbeet's avatar
Henri Verbeet committed
92

93
    wined3d_mutex_lock();
94 95
    hr = wined3d_swapchain_present(This->wined3d_swapchain, pSourceRect,
            pDestRect, hDestWindowOverride, pDirtyRegion, dwFlags);
96
    wined3d_mutex_unlock();
Henri Verbeet's avatar
Henri Verbeet committed
97 98

    return hr;
99 100
}

101 102 103
static HRESULT WINAPI IDirect3DSwapChain9Impl_GetFrontBufferData(IDirect3DSwapChain9 *iface,
        IDirect3DSurface9 *pDestSurface)
{
104
    IDirect3DSwapChain9Impl *This = (IDirect3DSwapChain9Impl *)iface;
105
    IDirect3DSurface9Impl *dst = unsafe_impl_from_IDirect3DSurface9(pDestSurface);
106
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
107 108

    TRACE("iface %p, surface %p.\n", iface, pDestSurface);
109

110
    wined3d_mutex_lock();
111
    hr = wined3d_swapchain_get_front_buffer_data(This->wined3d_swapchain, dst->wined3d_surface);
112 113
    wined3d_mutex_unlock();

114
    return hr;
115 116
}

117 118 119
static HRESULT WINAPI IDirect3DSwapChain9Impl_GetBackBuffer(IDirect3DSwapChain9 *iface,
        UINT iBackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface9 **ppBackBuffer)
{
120
    IDirect3DSwapChain9Impl *This = (IDirect3DSwapChain9Impl *)iface;
121
    struct wined3d_surface *wined3d_surface = NULL;
122
    HRESULT hr;
Oliver Stieber's avatar
Oliver Stieber committed
123

Henri Verbeet's avatar
Henri Verbeet committed
124 125
    TRACE("iface %p, backbuffer_idx %u, backbuffer_type %#x, backbuffer %p.\n",
            iface, iBackBuffer, Type, ppBackBuffer);
Oliver Stieber's avatar
Oliver Stieber committed
126

127
    wined3d_mutex_lock();
128
    hr = wined3d_swapchain_get_back_buffer(This->wined3d_swapchain,
129 130
            iBackBuffer, (WINED3DBACKBUFFER_TYPE)Type, &wined3d_surface);
    if (SUCCEEDED(hr) && wined3d_surface)
131
    {
132
       *ppBackBuffer = wined3d_surface_get_parent(wined3d_surface);
133
       IDirect3DSurface9_AddRef(*ppBackBuffer);
134
       wined3d_surface_decref(wined3d_surface);
Oliver Stieber's avatar
Oliver Stieber committed
135
    }
136 137
    wined3d_mutex_unlock();

138
    /* Do not touch the **ppBackBuffer pointer otherwise! (see device test) */
139
    return hr;
140 141
}

142
static HRESULT WINAPI IDirect3DSwapChain9Impl_GetRasterStatus(LPDIRECT3DSWAPCHAIN9 iface, D3DRASTER_STATUS* pRasterStatus) {
143
    IDirect3DSwapChain9Impl *This = (IDirect3DSwapChain9Impl *)iface;
144
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
145 146

    TRACE("iface %p, raster_status %p.\n", iface, pRasterStatus);
147

148
    wined3d_mutex_lock();
149
    hr = wined3d_swapchain_get_raster_status(This->wined3d_swapchain, (WINED3DRASTER_STATUS *)pRasterStatus);
150 151
    wined3d_mutex_unlock();

152
    return hr;
153 154
}

155
static HRESULT WINAPI IDirect3DSwapChain9Impl_GetDisplayMode(LPDIRECT3DSWAPCHAIN9 iface, D3DDISPLAYMODE* pMode) {
156
    IDirect3DSwapChain9Impl *This = (IDirect3DSwapChain9Impl *)iface;
157
    HRESULT hr;
Henri Verbeet's avatar
Henri Verbeet committed
158 159

    TRACE("iface %p, mode %p.\n", iface, pMode);
160

161
    wined3d_mutex_lock();
162
    hr = wined3d_swapchain_get_display_mode(This->wined3d_swapchain, (WINED3DDISPLAYMODE *)pMode);
163
    wined3d_mutex_unlock();
164 165 166

    if (SUCCEEDED(hr)) pMode->Format = d3dformat_from_wined3dformat(pMode->Format);

167
    return hr;
168 169
}

170 171
static HRESULT WINAPI IDirect3DSwapChain9Impl_GetDevice(IDirect3DSwapChain9 *iface, IDirect3DDevice9 **device)
{
Oliver Stieber's avatar
Oliver Stieber committed
172
    IDirect3DSwapChain9Impl *This = (IDirect3DSwapChain9Impl *)iface;
173

174
    TRACE("iface %p, device %p.\n", iface, device);
Oliver Stieber's avatar
Oliver Stieber committed
175

176 177
    *device = (IDirect3DDevice9 *)This->parentDevice;
    IDirect3DDevice9_AddRef(*device);
178

179 180 181
    TRACE("Returning device %p.\n", *device);

    return D3D_OK;
182 183
}

184
static HRESULT WINAPI IDirect3DSwapChain9Impl_GetPresentParameters(LPDIRECT3DSWAPCHAIN9 iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
185
    IDirect3DSwapChain9Impl *This = (IDirect3DSwapChain9Impl *)iface;
186
    WINED3DPRESENT_PARAMETERS winePresentParameters;
187 188
    HRESULT hr;

Henri Verbeet's avatar
Henri Verbeet committed
189
    TRACE("iface %p, parameters %p.\n", iface, pPresentationParameters);
190

191
    wined3d_mutex_lock();
192
    hr = wined3d_swapchain_get_present_parameters(This->wined3d_swapchain, &winePresentParameters);
193
    wined3d_mutex_unlock();
194 195 196

    pPresentationParameters->BackBufferWidth            = winePresentParameters.BackBufferWidth;
    pPresentationParameters->BackBufferHeight           = winePresentParameters.BackBufferHeight;
197
    pPresentationParameters->BackBufferFormat           = d3dformat_from_wined3dformat(winePresentParameters.BackBufferFormat);
198 199 200 201 202 203 204
    pPresentationParameters->BackBufferCount            = winePresentParameters.BackBufferCount;
    pPresentationParameters->MultiSampleType            = winePresentParameters.MultiSampleType;
    pPresentationParameters->MultiSampleQuality         = winePresentParameters.MultiSampleQuality;
    pPresentationParameters->SwapEffect                 = winePresentParameters.SwapEffect;
    pPresentationParameters->hDeviceWindow              = winePresentParameters.hDeviceWindow;
    pPresentationParameters->Windowed                   = winePresentParameters.Windowed;
    pPresentationParameters->EnableAutoDepthStencil     = winePresentParameters.EnableAutoDepthStencil;
205
    pPresentationParameters->AutoDepthStencilFormat     = d3dformat_from_wined3dformat(winePresentParameters.AutoDepthStencilFormat);
206 207 208 209 210
    pPresentationParameters->Flags                      = winePresentParameters.Flags;
    pPresentationParameters->FullScreen_RefreshRateInHz = winePresentParameters.FullScreen_RefreshRateInHz;
    pPresentationParameters->PresentationInterval       = winePresentParameters.PresentationInterval;

    return hr;
211 212 213
}


214
static const IDirect3DSwapChain9Vtbl Direct3DSwapChain9_Vtbl =
215 216 217 218 219 220 221 222 223 224 225 226 227
{
    IDirect3DSwapChain9Impl_QueryInterface,
    IDirect3DSwapChain9Impl_AddRef,
    IDirect3DSwapChain9Impl_Release,
    IDirect3DSwapChain9Impl_Present,
    IDirect3DSwapChain9Impl_GetFrontBufferData,
    IDirect3DSwapChain9Impl_GetBackBuffer,
    IDirect3DSwapChain9Impl_GetRasterStatus,
    IDirect3DSwapChain9Impl_GetDisplayMode,
    IDirect3DSwapChain9Impl_GetDevice,
    IDirect3DSwapChain9Impl_GetPresentParameters
};

228 229 230 231 232 233 234 235 236 237
static void STDMETHODCALLTYPE d3d9_swapchain_wined3d_object_released(void *parent)
{
    HeapFree(GetProcessHeap(), 0, parent);
}

static const struct wined3d_parent_ops d3d9_swapchain_wined3d_parent_ops =
{
    d3d9_swapchain_wined3d_object_released,
};

238 239 240 241 242
HRESULT swapchain_init(IDirect3DSwapChain9Impl *swapchain, IDirect3DDevice9Impl *device,
        D3DPRESENT_PARAMETERS *present_parameters)
{
    WINED3DPRESENT_PARAMETERS wined3d_parameters;
    HRESULT hr;
243

244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
    swapchain->ref = 1;
    swapchain->lpVtbl = &Direct3DSwapChain9_Vtbl;

    wined3d_parameters.BackBufferWidth = present_parameters->BackBufferWidth;
    wined3d_parameters.BackBufferHeight = present_parameters->BackBufferHeight;
    wined3d_parameters.BackBufferFormat = wined3dformat_from_d3dformat(present_parameters->BackBufferFormat);
    wined3d_parameters.BackBufferCount = max(1, present_parameters->BackBufferCount);
    wined3d_parameters.MultiSampleType = present_parameters->MultiSampleType;
    wined3d_parameters.MultiSampleQuality = present_parameters->MultiSampleQuality;
    wined3d_parameters.SwapEffect = present_parameters->SwapEffect;
    wined3d_parameters.hDeviceWindow = present_parameters->hDeviceWindow;
    wined3d_parameters.Windowed = present_parameters->Windowed;
    wined3d_parameters.EnableAutoDepthStencil = present_parameters->EnableAutoDepthStencil;
    wined3d_parameters.AutoDepthStencilFormat = wined3dformat_from_d3dformat(present_parameters->AutoDepthStencilFormat);
    wined3d_parameters.Flags = present_parameters->Flags;
    wined3d_parameters.FullScreen_RefreshRateInHz = present_parameters->FullScreen_RefreshRateInHz;
    wined3d_parameters.PresentationInterval = present_parameters->PresentationInterval;
    wined3d_parameters.AutoRestoreDisplayMode = TRUE;
Oliver Stieber's avatar
Oliver Stieber committed
262

263
    wined3d_mutex_lock();
264
    hr = wined3d_swapchain_create(device->wined3d_device, &wined3d_parameters,
265
            SURFACE_OPENGL, swapchain, &d3d9_swapchain_wined3d_parent_ops,
266
            &swapchain->wined3d_swapchain);
267
    wined3d_mutex_unlock();
268

269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
    present_parameters->BackBufferWidth = wined3d_parameters.BackBufferWidth;
    present_parameters->BackBufferHeight = wined3d_parameters.BackBufferHeight;
    present_parameters->BackBufferFormat = d3dformat_from_wined3dformat(wined3d_parameters.BackBufferFormat);
    present_parameters->BackBufferCount = wined3d_parameters.BackBufferCount;
    present_parameters->MultiSampleType = wined3d_parameters.MultiSampleType;
    present_parameters->MultiSampleQuality = wined3d_parameters.MultiSampleQuality;
    present_parameters->SwapEffect = wined3d_parameters.SwapEffect;
    present_parameters->hDeviceWindow = wined3d_parameters.hDeviceWindow;
    present_parameters->Windowed = wined3d_parameters.Windowed;
    present_parameters->EnableAutoDepthStencil = wined3d_parameters.EnableAutoDepthStencil;
    present_parameters->AutoDepthStencilFormat = d3dformat_from_wined3dformat(wined3d_parameters.AutoDepthStencilFormat);
    present_parameters->Flags = wined3d_parameters.Flags;
    present_parameters->FullScreen_RefreshRateInHz = wined3d_parameters.FullScreen_RefreshRateInHz;
    present_parameters->PresentationInterval = wined3d_parameters.PresentationInterval;

    if (FAILED(hr))
    {
        WARN("Failed to create wined3d swapchain, hr %#x.\n", hr);
        return hr;
Oliver Stieber's avatar
Oliver Stieber committed
288
    }
289

290
    swapchain->parentDevice = &device->IDirect3DDevice9Ex_iface;
291 292 293
    IDirect3DDevice9Ex_AddRef(swapchain->parentDevice);

    return D3D_OK;
294
}