1/*
2 * Copyright 2011 Joakim Sindholt <opensource@zhasha.com>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE. */
22
23#include "device9.h"
24#include "device9ex.h"
25#include "nine_pipe.h"
26#include "swapchain9ex.h"
27
28#include "nine_helpers.h"
29
30#include "util/macros.h"
31
32#define DBG_CHANNEL DBG_DEVICE
33
34static HRESULT
35NineDevice9Ex_ctor( struct NineDevice9Ex *This,
36                    struct NineUnknownParams *pParams,
37                    struct pipe_screen *pScreen,
38                    D3DDEVICE_CREATION_PARAMETERS *pCreationParameters,
39                    D3DCAPS9 *pCaps,
40                    D3DPRESENT_PARAMETERS *pPresentationParameters,
41                    D3DDISPLAYMODEEX *pFullscreenDisplayMode,
42                    IDirect3D9Ex *pD3D9Ex,
43                    ID3DPresentGroup *pPresentationGroup,
44                    struct d3dadapter9_context *pCTX,
45                    int minorVersionNum )
46{
47    DBG("This=%p pParams=%p pScreen=%p pCreationParameters=%p pCaps=%p "
48        "pPresentationParameters=%p pFullscreenDisplayMode=%p "
49        "pD3D9Ex=%p pPresentationGroup=%p pCTX=%p\n",
50        This, pParams, pScreen, pCreationParameters, pCaps,
51        pPresentationParameters, pFullscreenDisplayMode,
52        pD3D9Ex, pPresentationGroup, pCTX);
53
54    return NineDevice9_ctor(&This->base, pParams,
55                            pScreen, pCreationParameters, pCaps,
56                            pPresentationParameters,
57                            (IDirect3D9 *)pD3D9Ex, pPresentationGroup, pCTX,
58                            TRUE, pFullscreenDisplayMode, minorVersionNum);
59}
60
61static void
62NineDevice9Ex_dtor( struct NineDevice9Ex *This )
63{
64    NineDevice9_dtor(&This->base);
65}
66
67HRESULT NINE_WINAPI
68NineDevice9Ex_SetConvolutionMonoKernel( UNUSED struct NineDevice9Ex *This,
69                                        UNUSED UINT width,
70                                        UNUSED UINT height,
71                                        UNUSED float *rows,
72                                        UNUSED float *columns )
73{
74    DBG("This\n");
75    STUB(D3D_OK);
76}
77
78HRESULT NINE_WINAPI
79NineDevice9Ex_ComposeRects( UNUSED struct NineDevice9Ex *This,
80                            UNUSED IDirect3DSurface9 *pSrc,
81                            UNUSED IDirect3DSurface9 *pDst,
82                            UNUSED IDirect3DVertexBuffer9 *pSrcRectDescs,
83                            UNUSED UINT NumRects,
84                            UNUSED IDirect3DVertexBuffer9 *pDstRectDescs,
85                            UNUSED D3DCOMPOSERECTSOP Operation,
86                            UNUSED int Xoffset,
87                            UNUSED int Yoffset )
88{
89    DBG("This\n");
90    STUB(D3D_OK);
91}
92
93HRESULT NINE_WINAPI
94NineDevice9Ex_PresentEx( struct NineDevice9Ex *This,
95                         const RECT *pSourceRect,
96                         const RECT *pDestRect,
97                         HWND hDestWindowOverride,
98                         const RGNDATA *pDirtyRegion,
99                         DWORD dwFlags )
100{
101    unsigned i;
102    HRESULT hr;
103
104    DBG("This=%p pSourceRect=%p pDestRect=%p hDestWindowOverride=%p "
105        "pDirtyRegion=%p dwFlags=%d\n",
106        This, pSourceRect, pDestRect, hDestWindowOverride,
107        pDirtyRegion, dwFlags);
108
109    for (i = 0; i < This->base.nswapchains; i++) {
110        hr = NineSwapChain9_Present(This->base.swapchains[i], pSourceRect, pDestRect,
111                                    hDestWindowOverride, pDirtyRegion, dwFlags);
112        if (FAILED(hr)) { return hr; }
113    }
114
115    return D3D_OK;
116}
117
118HRESULT NINE_WINAPI
119NineDevice9Ex_GetGPUThreadPriority( struct NineDevice9Ex *This,
120                                    INT *pPriority )
121{
122    DBG("This\n");
123    user_assert(pPriority != NULL, D3DERR_INVALIDCALL);
124    *pPriority = This->base.gpu_priority;
125    return D3D_OK;
126}
127
128HRESULT NINE_WINAPI
129NineDevice9Ex_SetGPUThreadPriority( struct NineDevice9Ex *This,
130                                    INT Priority )
131{
132    DBG("This\n");
133    user_assert(Priority >= -7 && Priority <= 7, D3DERR_INVALIDCALL);
134    This->base.gpu_priority = Priority;
135    return D3D_OK;
136}
137
138HRESULT NINE_WINAPI
139NineDevice9Ex_WaitForVBlank( UNUSED struct NineDevice9Ex *This,
140                             UNUSED UINT iSwapChain )
141{
142    DBG("This\n");
143    STUB(D3D_OK);
144}
145
146HRESULT NINE_WINAPI
147NineDevice9Ex_CheckResourceResidency( UNUSED struct NineDevice9Ex *This,
148                                      UNUSED IDirect3DResource9 **pResourceArray,
149                                      UNUSED UINT32 NumResources )
150{
151    DBG("This\n");
152    STUB(D3D_OK);
153}
154
155HRESULT NINE_WINAPI
156NineDevice9Ex_SetMaximumFrameLatency( struct NineDevice9Ex *This,
157                                      UINT MaxLatency )
158{
159    DBG("This\n");
160    This->base.max_frame_latency = MaxLatency;
161    return D3D_OK;
162}
163
164HRESULT NINE_WINAPI
165NineDevice9Ex_GetMaximumFrameLatency( struct NineDevice9Ex *This,
166                                      UINT *pMaxLatency )
167{
168    DBG("This\n");
169    user_assert(pMaxLatency != NULL, D3DERR_INVALIDCALL);
170    *pMaxLatency = This->base.max_frame_latency;
171    return D3D_OK;
172}
173
174HRESULT NINE_WINAPI
175NineDevice9Ex_CheckDeviceState( struct NineDevice9Ex *This,
176                                HWND hDestinationWindow )
177{
178    DBG("This=%p hDestinationWindow=%p\n",
179        This, hDestinationWindow);
180
181    user_assert(!This->base.swapchains[0]->params.Windowed, D3D_OK);
182
183    if (This->base.params.hFocusWindow == hDestinationWindow) {
184        if (NineSwapChain9_GetOccluded(This->base.swapchains[0]))
185            return S_PRESENT_OCCLUDED;
186    } else if(!NineSwapChain9_GetOccluded(This->base.swapchains[0])) {
187        return S_PRESENT_OCCLUDED;
188    }
189    /* TODO: handle the other return values */
190    return D3D_OK;
191}
192
193HRESULT NINE_WINAPI
194NineDevice9Ex_CreateRenderTargetEx( struct NineDevice9Ex *This,
195                                    UINT Width,
196                                    UINT Height,
197                                    D3DFORMAT Format,
198                                    D3DMULTISAMPLE_TYPE MultiSample,
199                                    DWORD MultisampleQuality,
200                                    BOOL Lockable,
201                                    IDirect3DSurface9 **ppSurface,
202                                    HANDLE *pSharedHandle,
203                                    UNUSED DWORD Usage )
204{
205    DBG("This\n");
206    /* The Create*Ex functions only purpose seem to introduce the
207     * Usage field, to pass the new d3d9ex flags on secure/restricted
208     * content.
209     * TODO: Return error on invalid Usage.
210     * TODO: Store Usage in the surface descriptor, in case the
211     * app checks */
212    return NineDevice9_CreateRenderTarget(&This->base,
213                                          Width,
214                                          Height,
215                                          Format,
216                                          MultiSample,
217                                          MultisampleQuality,
218                                          Lockable,
219                                          ppSurface,
220                                          pSharedHandle);
221}
222
223HRESULT NINE_WINAPI
224NineDevice9Ex_CreateOffscreenPlainSurfaceEx( struct NineDevice9Ex *This,
225                                             UINT Width,
226                                             UINT Height,
227                                             D3DFORMAT Format,
228                                             D3DPOOL Pool,
229                                             IDirect3DSurface9 **ppSurface,
230                                             HANDLE *pSharedHandle,
231                                             UNUSED DWORD Usage )
232{
233    DBG("This\n");
234    /* The Create*Ex functions only purpose seem to introduce the
235     * Usage field, to pass the new d3d9ex flags on secure/restricted
236     * content.
237     * TODO: Return error on invalid Usage.
238     * TODO: Store Usage in the surface descriptor, in case the
239     * app checks */
240    return NineDevice9_CreateOffscreenPlainSurface(&This->base,
241                                                   Width,
242                                                   Height,
243                                                   Format,
244                                                   Pool,
245                                                   ppSurface,
246                                                   pSharedHandle);
247}
248
249HRESULT NINE_WINAPI
250NineDevice9Ex_CreateDepthStencilSurfaceEx( struct NineDevice9Ex *This,
251                                           UINT Width,
252                                           UINT Height,
253                                           D3DFORMAT Format,
254                                           D3DMULTISAMPLE_TYPE MultiSample,
255                                           DWORD MultisampleQuality,
256                                           BOOL Discard,
257                                           IDirect3DSurface9 **ppSurface,
258                                           HANDLE *pSharedHandle,
259                                           UNUSED DWORD Usage )
260{
261    DBG("This\n");
262    /* The Create*Ex functions only purpose seem to introduce the
263     * Usage field, to pass the new d3d9ex flags on secure/restricted
264     * content.
265     * TODO: Return error on invalid Usage.
266     * TODO: Store Usage in the surface descriptor, in case the
267     * app checks */
268    return NineDevice9_CreateDepthStencilSurface(&This->base,
269                                                 Width,
270                                                 Height,
271                                                 Format,
272                                                 MultiSample,
273                                                 MultisampleQuality,
274                                                 Discard,
275                                                 ppSurface,
276                                                 pSharedHandle);
277}
278
279HRESULT NINE_WINAPI
280NineDevice9Ex_ResetEx( struct NineDevice9Ex *This,
281                       D3DPRESENT_PARAMETERS *pPresentationParameters,
282                       D3DDISPLAYMODEEX *pFullscreenDisplayMode )
283{
284    HRESULT hr = D3D_OK;
285    float MinZ, MaxZ;
286    unsigned i;
287
288    DBG("This=%p pPresentationParameters=%p pFullscreenDisplayMode=%p\n", This, pPresentationParameters, pFullscreenDisplayMode);
289
290    for (i = 0; i < This->base.nswapchains; ++i) {
291        D3DDISPLAYMODEEX *mode = NULL;
292        D3DPRESENT_PARAMETERS *params = &pPresentationParameters[i];
293        if (pFullscreenDisplayMode) mode = &(pFullscreenDisplayMode[i]);
294        hr = NineSwapChain9_Resize(This->base.swapchains[i], params, mode);
295        if (FAILED(hr))
296            break;
297    }
298
299    MinZ = This->base.state.viewport.MinZ; /* These are preserved */
300    MaxZ = This->base.state.viewport.MaxZ;
301    NineDevice9_SetRenderTarget(
302        (struct NineDevice9 *)This, 0, (IDirect3DSurface9 *)This->base.swapchains[0]->buffers[0]);
303    This->base.state.viewport.MinZ = MinZ;
304    This->base.state.viewport.MaxZ = MaxZ;
305    nine_context_set_viewport(&This->base, &This->base.state.viewport);
306
307    if (This->base.nswapchains && This->base.swapchains[0]->params.EnableAutoDepthStencil)
308        NineDevice9_SetDepthStencilSurface(
309            &This->base, (IDirect3DSurface9 *)This->base.swapchains[0]->zsbuf);
310
311    return hr;
312}
313
314HRESULT NINE_WINAPI
315NineDevice9Ex_Reset( struct NineDevice9Ex *This,
316                     D3DPRESENT_PARAMETERS *pPresentationParameters )
317{
318    HRESULT hr = D3D_OK;
319    float MinZ, MaxZ;
320    unsigned i;
321
322    DBG("This=%p pPresentationParameters=%p\n", This, pPresentationParameters);
323
324    for (i = 0; i < This->base.nswapchains; ++i) {
325        D3DPRESENT_PARAMETERS *params = &pPresentationParameters[i];
326        hr = NineSwapChain9_Resize(This->base.swapchains[i], params, NULL);
327        if (FAILED(hr))
328            break;
329    }
330
331    MinZ = This->base.state.viewport.MinZ; /* These are preserved */
332    MaxZ = This->base.state.viewport.MaxZ;
333    NineDevice9_SetRenderTarget(
334        (struct NineDevice9 *)This, 0, (IDirect3DSurface9 *)This->base.swapchains[0]->buffers[0]);
335    This->base.state.viewport.MinZ = MinZ;
336    This->base.state.viewport.MaxZ = MaxZ;
337    nine_context_set_viewport(&This->base, &This->base.state.viewport);
338
339    if (This->base.nswapchains && This->base.swapchains[0]->params.EnableAutoDepthStencil)
340        NineDevice9_SetDepthStencilSurface(
341            &This->base, (IDirect3DSurface9 *)This->base.swapchains[0]->zsbuf);
342
343    return hr;
344}
345
346HRESULT NINE_WINAPI
347NineDevice9Ex_GetDisplayModeEx( struct NineDevice9Ex *This,
348                                UINT iSwapChain,
349                                D3DDISPLAYMODEEX *pMode,
350                                D3DDISPLAYROTATION *pRotation )
351{
352    struct NineSwapChain9Ex *swapchain;
353
354    DBG("This=%p iSwapChain=%u pMode=%p pRotation=%p\n",
355        This, iSwapChain, pMode, pRotation);
356
357    user_assert(iSwapChain < This->base.nswapchains, D3DERR_INVALIDCALL);
358
359    swapchain = NineSwapChain9Ex(This->base.swapchains[iSwapChain]);
360    return NineSwapChain9Ex_GetDisplayModeEx(swapchain, pMode, pRotation);
361}
362
363HRESULT NINE_WINAPI
364NineDevice9Ex_TestCooperativeLevel( UNUSED struct NineDevice9Ex *This )
365{
366    DBG("This\n");
367    return D3D_OK;
368}
369
370
371IDirect3DDevice9ExVtbl NineDevice9Ex_vtable = {
372    (void *)NineUnknown_QueryInterface,
373    (void *)NineUnknown_AddRef,
374    (void *)NineUnknown_Release,
375    (void *)NineDevice9Ex_TestCooperativeLevel,
376    (void *)NineDevice9_GetAvailableTextureMem,
377    (void *)NineDevice9_EvictManagedResources,
378    (void *)NineDevice9_GetDirect3D,
379    (void *)NineDevice9_GetDeviceCaps,
380    (void *)NineDevice9_GetDisplayMode,
381    (void *)NineDevice9_GetCreationParameters,
382    (void *)NineDevice9_SetCursorProperties,
383    (void *)NineDevice9_SetCursorPosition,
384    (void *)NineDevice9_ShowCursor,
385    (void *)NineDevice9_CreateAdditionalSwapChain,
386    (void *)NineDevice9_GetSwapChain,
387    (void *)NineDevice9_GetNumberOfSwapChains,
388    (void *)NineDevice9Ex_Reset,
389    (void *)NineDevice9_Present,
390    (void *)NineDevice9_GetBackBuffer,
391    (void *)NineDevice9_GetRasterStatus,
392    (void *)NineDevice9_SetDialogBoxMode,
393    (void *)NineDevice9_SetGammaRamp,
394    (void *)NineDevice9_GetGammaRamp,
395    (void *)NineDevice9_CreateTexture,
396    (void *)NineDevice9_CreateVolumeTexture,
397    (void *)NineDevice9_CreateCubeTexture,
398    (void *)NineDevice9_CreateVertexBuffer,
399    (void *)NineDevice9_CreateIndexBuffer,
400    (void *)NineDevice9_CreateRenderTarget,
401    (void *)NineDevice9_CreateDepthStencilSurface,
402    (void *)NineDevice9_UpdateSurface,
403    (void *)NineDevice9_UpdateTexture,
404    (void *)NineDevice9_GetRenderTargetData,
405    (void *)NineDevice9_GetFrontBufferData,
406    (void *)NineDevice9_StretchRect,
407    (void *)NineDevice9_ColorFill,
408    (void *)NineDevice9_CreateOffscreenPlainSurface,
409    (void *)NineDevice9_SetRenderTarget,
410    (void *)NineDevice9_GetRenderTarget,
411    (void *)NineDevice9_SetDepthStencilSurface,
412    (void *)NineDevice9_GetDepthStencilSurface,
413    (void *)NineDevice9_BeginScene,
414    (void *)NineDevice9_EndScene,
415    (void *)NineDevice9_Clear,
416    (void *)NineDevice9_SetTransform,
417    (void *)NineDevice9_GetTransform,
418    (void *)NineDevice9_MultiplyTransform,
419    (void *)NineDevice9_SetViewport,
420    (void *)NineDevice9_GetViewport,
421    (void *)NineDevice9_SetMaterial,
422    (void *)NineDevice9_GetMaterial,
423    (void *)NineDevice9_SetLight,
424    (void *)NineDevice9_GetLight,
425    (void *)NineDevice9_LightEnable,
426    (void *)NineDevice9_GetLightEnable,
427    (void *)NineDevice9_SetClipPlane,
428    (void *)NineDevice9_GetClipPlane,
429    (void *)NineDevice9_SetRenderState,
430    (void *)NineDevice9_GetRenderState,
431    (void *)NineDevice9_CreateStateBlock,
432    (void *)NineDevice9_BeginStateBlock,
433    (void *)NineDevice9_EndStateBlock,
434    (void *)NineDevice9_SetClipStatus,
435    (void *)NineDevice9_GetClipStatus,
436    (void *)NineDevice9_GetTexture,
437    (void *)NineDevice9_SetTexture,
438    (void *)NineDevice9_GetTextureStageState,
439    (void *)NineDevice9_SetTextureStageState,
440    (void *)NineDevice9_GetSamplerState,
441    (void *)NineDevice9_SetSamplerState,
442    (void *)NineDevice9_ValidateDevice,
443    (void *)NineDevice9_SetPaletteEntries,
444    (void *)NineDevice9_GetPaletteEntries,
445    (void *)NineDevice9_SetCurrentTexturePalette,
446    (void *)NineDevice9_GetCurrentTexturePalette,
447    (void *)NineDevice9_SetScissorRect,
448    (void *)NineDevice9_GetScissorRect,
449    (void *)NineDevice9_SetSoftwareVertexProcessing,
450    (void *)NineDevice9_GetSoftwareVertexProcessing,
451    (void *)NineDevice9_SetNPatchMode,
452    (void *)NineDevice9_GetNPatchMode,
453    (void *)NineDevice9_DrawPrimitive,
454    (void *)NineDevice9_DrawIndexedPrimitive,
455    (void *)NineDevice9_DrawPrimitiveUP,
456    (void *)NineDevice9_DrawIndexedPrimitiveUP,
457    (void *)NineDevice9_ProcessVertices,
458    (void *)NineDevice9_CreateVertexDeclaration,
459    (void *)NineDevice9_SetVertexDeclaration,
460    (void *)NineDevice9_GetVertexDeclaration,
461    (void *)NineDevice9_SetFVF,
462    (void *)NineDevice9_GetFVF,
463    (void *)NineDevice9_CreateVertexShader,
464    (void *)NineDevice9_SetVertexShader,
465    (void *)NineDevice9_GetVertexShader,
466    (void *)NineDevice9_SetVertexShaderConstantF,
467    (void *)NineDevice9_GetVertexShaderConstantF,
468    (void *)NineDevice9_SetVertexShaderConstantI,
469    (void *)NineDevice9_GetVertexShaderConstantI,
470    (void *)NineDevice9_SetVertexShaderConstantB,
471    (void *)NineDevice9_GetVertexShaderConstantB,
472    (void *)NineDevice9_SetStreamSource,
473    (void *)NineDevice9_GetStreamSource,
474    (void *)NineDevice9_SetStreamSourceFreq,
475    (void *)NineDevice9_GetStreamSourceFreq,
476    (void *)NineDevice9_SetIndices,
477    (void *)NineDevice9_GetIndices,
478    (void *)NineDevice9_CreatePixelShader,
479    (void *)NineDevice9_SetPixelShader,
480    (void *)NineDevice9_GetPixelShader,
481    (void *)NineDevice9_SetPixelShaderConstantF,
482    (void *)NineDevice9_GetPixelShaderConstantF,
483    (void *)NineDevice9_SetPixelShaderConstantI,
484    (void *)NineDevice9_GetPixelShaderConstantI,
485    (void *)NineDevice9_SetPixelShaderConstantB,
486    (void *)NineDevice9_GetPixelShaderConstantB,
487    (void *)NineDevice9_DrawRectPatch,
488    (void *)NineDevice9_DrawTriPatch,
489    (void *)NineDevice9_DeletePatch,
490    (void *)NineDevice9_CreateQuery,
491    (void *)NineDevice9Ex_SetConvolutionMonoKernel,
492    (void *)NineDevice9Ex_ComposeRects,
493    (void *)NineDevice9Ex_PresentEx,
494    (void *)NineDevice9Ex_GetGPUThreadPriority,
495    (void *)NineDevice9Ex_SetGPUThreadPriority,
496    (void *)NineDevice9Ex_WaitForVBlank,
497    (void *)NineDevice9Ex_CheckResourceResidency,
498    (void *)NineDevice9Ex_SetMaximumFrameLatency,
499    (void *)NineDevice9Ex_GetMaximumFrameLatency,
500    (void *)NineDevice9Ex_CheckDeviceState,
501    (void *)NineDevice9Ex_CreateRenderTargetEx,
502    (void *)NineDevice9Ex_CreateOffscreenPlainSurfaceEx,
503    (void *)NineDevice9Ex_CreateDepthStencilSurfaceEx,
504    (void *)NineDevice9Ex_ResetEx,
505    (void *)NineDevice9Ex_GetDisplayModeEx
506};
507
508static const GUID *NineDevice9Ex_IIDs[] = {
509    &IID_IDirect3DDevice9Ex,
510    &IID_IDirect3DDevice9,
511    &IID_IUnknown,
512    NULL
513};
514
515HRESULT
516NineDevice9Ex_new( struct pipe_screen *pScreen,
517                   D3DDEVICE_CREATION_PARAMETERS *pCreationParameters,
518                   D3DCAPS9 *pCaps,
519                   D3DPRESENT_PARAMETERS *pPresentationParameters,
520                   D3DDISPLAYMODEEX *pFullscreenDisplayMode,
521                   IDirect3D9Ex *pD3D9Ex,
522                   ID3DPresentGroup *pPresentationGroup,
523                   struct d3dadapter9_context *pCTX,
524                   struct NineDevice9Ex **ppOut,
525                   int minorVersionNum )
526{
527    BOOL lock;
528    lock = !!(pCreationParameters->BehaviorFlags & D3DCREATE_MULTITHREADED);
529
530    NINE_NEW(Device9Ex, ppOut, lock,
531             pScreen, pCreationParameters, pCaps, pPresentationParameters,
532             pFullscreenDisplayMode, pD3D9Ex, pPresentationGroup, pCTX, minorVersionNum );
533}
534
535