xref: /aosp_15_r20/external/mesa3d/src/gallium/frontends/nine/swapchain9.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright 2011 Joakim Sindholt <[email protected]>
3*61046927SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
4*61046927SAndroid Build Coastguard Worker  */
5*61046927SAndroid Build Coastguard Worker 
6*61046927SAndroid Build Coastguard Worker #include "swapchain9.h"
7*61046927SAndroid Build Coastguard Worker #include "surface9.h"
8*61046927SAndroid Build Coastguard Worker #include "device9.h"
9*61046927SAndroid Build Coastguard Worker 
10*61046927SAndroid Build Coastguard Worker #include "nine_helpers.h"
11*61046927SAndroid Build Coastguard Worker #include "nine_pipe.h"
12*61046927SAndroid Build Coastguard Worker #include "nine_dump.h"
13*61046927SAndroid Build Coastguard Worker 
14*61046927SAndroid Build Coastguard Worker #include "util/u_atomic.h"
15*61046927SAndroid Build Coastguard Worker #include "util/u_inlines.h"
16*61046927SAndroid Build Coastguard Worker #include "util/u_surface.h"
17*61046927SAndroid Build Coastguard Worker #include "hud/hud_context.h"
18*61046927SAndroid Build Coastguard Worker #include "frontend/drm_driver.h"
19*61046927SAndroid Build Coastguard Worker 
20*61046927SAndroid Build Coastguard Worker #include "threadpool.h"
21*61046927SAndroid Build Coastguard Worker 
22*61046927SAndroid Build Coastguard Worker #define DBG_CHANNEL DBG_SWAPCHAIN
23*61046927SAndroid Build Coastguard Worker 
24*61046927SAndroid Build Coastguard Worker #define UNTESTED(n) DBG("UNTESTED point %d. Please tell if it worked\n", n)
25*61046927SAndroid Build Coastguard Worker 
26*61046927SAndroid Build Coastguard Worker HRESULT
NineSwapChain9_ctor(struct NineSwapChain9 * This,struct NineUnknownParams * pParams,BOOL implicit,ID3DPresent * pPresent,D3DPRESENT_PARAMETERS * pPresentationParameters,struct d3dadapter9_context * pCTX,HWND hFocusWindow,D3DDISPLAYMODEEX * mode)27*61046927SAndroid Build Coastguard Worker NineSwapChain9_ctor( struct NineSwapChain9 *This,
28*61046927SAndroid Build Coastguard Worker                      struct NineUnknownParams *pParams,
29*61046927SAndroid Build Coastguard Worker                      BOOL implicit,
30*61046927SAndroid Build Coastguard Worker                      ID3DPresent *pPresent,
31*61046927SAndroid Build Coastguard Worker                      D3DPRESENT_PARAMETERS *pPresentationParameters,
32*61046927SAndroid Build Coastguard Worker                      struct d3dadapter9_context *pCTX,
33*61046927SAndroid Build Coastguard Worker                      HWND hFocusWindow,
34*61046927SAndroid Build Coastguard Worker                      D3DDISPLAYMODEEX *mode )
35*61046927SAndroid Build Coastguard Worker {
36*61046927SAndroid Build Coastguard Worker     HRESULT hr;
37*61046927SAndroid Build Coastguard Worker     int i;
38*61046927SAndroid Build Coastguard Worker 
39*61046927SAndroid Build Coastguard Worker     DBG("This=%p pDevice=%p pPresent=%p pCTX=%p hFocusWindow=%p\n",
40*61046927SAndroid Build Coastguard Worker         This, pParams->device, pPresent, pCTX, hFocusWindow);
41*61046927SAndroid Build Coastguard Worker 
42*61046927SAndroid Build Coastguard Worker     hr = NineUnknown_ctor(&This->base, pParams);
43*61046927SAndroid Build Coastguard Worker     if (FAILED(hr))
44*61046927SAndroid Build Coastguard Worker         return hr;
45*61046927SAndroid Build Coastguard Worker 
46*61046927SAndroid Build Coastguard Worker     This->screen = NineDevice9_GetScreen(This->base.device);
47*61046927SAndroid Build Coastguard Worker     This->implicit = implicit;
48*61046927SAndroid Build Coastguard Worker     This->actx = pCTX;
49*61046927SAndroid Build Coastguard Worker     This->present = pPresent;
50*61046927SAndroid Build Coastguard Worker     This->mode = NULL;
51*61046927SAndroid Build Coastguard Worker 
52*61046927SAndroid Build Coastguard Worker     ID3DPresent_AddRef(pPresent);
53*61046927SAndroid Build Coastguard Worker     if (This->base.device->minor_version_num > 2) {
54*61046927SAndroid Build Coastguard Worker         D3DPRESENT_PARAMETERS2 params2;
55*61046927SAndroid Build Coastguard Worker 
56*61046927SAndroid Build Coastguard Worker         memset(&params2, 0, sizeof(D3DPRESENT_PARAMETERS2));
57*61046927SAndroid Build Coastguard Worker         params2.AllowDISCARDDelayedRelease = This->actx->discard_delayed_release;
58*61046927SAndroid Build Coastguard Worker         params2.TearFreeDISCARD = This->actx->tearfree_discard;
59*61046927SAndroid Build Coastguard Worker         ID3DPresent_SetPresentParameters2(pPresent, &params2);
60*61046927SAndroid Build Coastguard Worker     }
61*61046927SAndroid Build Coastguard Worker 
62*61046927SAndroid Build Coastguard Worker     if (!pPresentationParameters->hDeviceWindow)
63*61046927SAndroid Build Coastguard Worker         pPresentationParameters->hDeviceWindow = hFocusWindow;
64*61046927SAndroid Build Coastguard Worker 
65*61046927SAndroid Build Coastguard Worker     This->rendering_done = false;
66*61046927SAndroid Build Coastguard Worker     This->pool = NULL;
67*61046927SAndroid Build Coastguard Worker     for (i = 0; i < D3DPRESENT_BACK_BUFFERS_MAX_EX + 1; i++) {
68*61046927SAndroid Build Coastguard Worker         This->pending_presentation[i] = calloc(1, sizeof(BOOL));
69*61046927SAndroid Build Coastguard Worker         if (!This->pending_presentation[i])
70*61046927SAndroid Build Coastguard Worker             return E_OUTOFMEMORY;
71*61046927SAndroid Build Coastguard Worker     }
72*61046927SAndroid Build Coastguard Worker     return NineSwapChain9_Resize(This, pPresentationParameters, mode);
73*61046927SAndroid Build Coastguard Worker }
74*61046927SAndroid Build Coastguard Worker 
75*61046927SAndroid Build Coastguard Worker static D3DWindowBuffer *
D3DWindowBuffer_create(struct NineSwapChain9 * This,struct pipe_resource * resource,int depth,int for_frontbuffer_reading)76*61046927SAndroid Build Coastguard Worker D3DWindowBuffer_create(struct NineSwapChain9 *This,
77*61046927SAndroid Build Coastguard Worker                        struct pipe_resource *resource,
78*61046927SAndroid Build Coastguard Worker                        int depth,
79*61046927SAndroid Build Coastguard Worker                        int for_frontbuffer_reading)
80*61046927SAndroid Build Coastguard Worker {
81*61046927SAndroid Build Coastguard Worker     D3DWindowBuffer *ret;
82*61046927SAndroid Build Coastguard Worker     struct pipe_context *pipe = nine_context_get_pipe_acquire(This->base.device);
83*61046927SAndroid Build Coastguard Worker     struct winsys_handle whandle;
84*61046927SAndroid Build Coastguard Worker     int stride, dmaBufFd;
85*61046927SAndroid Build Coastguard Worker     HRESULT hr;
86*61046927SAndroid Build Coastguard Worker 
87*61046927SAndroid Build Coastguard Worker     memset(&whandle, 0, sizeof(whandle));
88*61046927SAndroid Build Coastguard Worker     whandle.type = WINSYS_HANDLE_TYPE_FD;
89*61046927SAndroid Build Coastguard Worker     if (!This->screen->resource_get_handle(This->screen, pipe, resource,
90*61046927SAndroid Build Coastguard Worker                                            &whandle,
91*61046927SAndroid Build Coastguard Worker                                            for_frontbuffer_reading ?
92*61046927SAndroid Build Coastguard Worker                                                PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE :
93*61046927SAndroid Build Coastguard Worker                                                PIPE_HANDLE_USAGE_EXPLICIT_FLUSH)) {
94*61046927SAndroid Build Coastguard Worker         ERR("Failed to get handle for resource\n");
95*61046927SAndroid Build Coastguard Worker         return NULL;
96*61046927SAndroid Build Coastguard Worker     }
97*61046927SAndroid Build Coastguard Worker     nine_context_get_pipe_release(This->base.device);
98*61046927SAndroid Build Coastguard Worker     stride = whandle.stride;
99*61046927SAndroid Build Coastguard Worker     dmaBufFd = whandle.handle;
100*61046927SAndroid Build Coastguard Worker     hr = ID3DPresent_NewD3DWindowBufferFromDmaBuf(This->present,
101*61046927SAndroid Build Coastguard Worker                                                   dmaBufFd,
102*61046927SAndroid Build Coastguard Worker                                                   resource->width0,
103*61046927SAndroid Build Coastguard Worker                                                   resource->height0,
104*61046927SAndroid Build Coastguard Worker                                                   stride,
105*61046927SAndroid Build Coastguard Worker                                                   depth,
106*61046927SAndroid Build Coastguard Worker                                                   32,
107*61046927SAndroid Build Coastguard Worker                                                   &ret);
108*61046927SAndroid Build Coastguard Worker     assert (SUCCEEDED(hr));
109*61046927SAndroid Build Coastguard Worker 
110*61046927SAndroid Build Coastguard Worker     if (FAILED(hr)) {
111*61046927SAndroid Build Coastguard Worker         ERR("Failed to create new D3DWindowBufferFromDmaBuf\n");
112*61046927SAndroid Build Coastguard Worker         return NULL;
113*61046927SAndroid Build Coastguard Worker     }
114*61046927SAndroid Build Coastguard Worker     return ret;
115*61046927SAndroid Build Coastguard Worker }
116*61046927SAndroid Build Coastguard Worker 
117*61046927SAndroid Build Coastguard Worker static void
D3DWindowBuffer_release(struct NineSwapChain9 * This,D3DWindowBuffer * present_handle)118*61046927SAndroid Build Coastguard Worker D3DWindowBuffer_release(struct NineSwapChain9 *This,
119*61046927SAndroid Build Coastguard Worker                         D3DWindowBuffer *present_handle)
120*61046927SAndroid Build Coastguard Worker {
121*61046927SAndroid Build Coastguard Worker     int i;
122*61046927SAndroid Build Coastguard Worker 
123*61046927SAndroid Build Coastguard Worker     /* IsBufferReleased API not available */
124*61046927SAndroid Build Coastguard Worker     if (This->base.device->minor_version_num <= 2) {
125*61046927SAndroid Build Coastguard Worker         ID3DPresent_DestroyD3DWindowBuffer(This->present, present_handle);
126*61046927SAndroid Build Coastguard Worker         return;
127*61046927SAndroid Build Coastguard Worker     }
128*61046927SAndroid Build Coastguard Worker 
129*61046927SAndroid Build Coastguard Worker     /* Add it to the 'pending release' list */
130*61046927SAndroid Build Coastguard Worker     for (i = 0; i < D3DPRESENT_BACK_BUFFERS_MAX_EX + 1; i++) {
131*61046927SAndroid Build Coastguard Worker         if (!This->present_handles_pending_release[i]) {
132*61046927SAndroid Build Coastguard Worker             This->present_handles_pending_release[i] = present_handle;
133*61046927SAndroid Build Coastguard Worker             break;
134*61046927SAndroid Build Coastguard Worker         }
135*61046927SAndroid Build Coastguard Worker     }
136*61046927SAndroid Build Coastguard Worker     if (i == (D3DPRESENT_BACK_BUFFERS_MAX_EX + 1)) {
137*61046927SAndroid Build Coastguard Worker         ERR("Server not releasing buffers...\n");
138*61046927SAndroid Build Coastguard Worker         assert(false);
139*61046927SAndroid Build Coastguard Worker     }
140*61046927SAndroid Build Coastguard Worker 
141*61046927SAndroid Build Coastguard Worker     /* Destroy elements of the list released by the server */
142*61046927SAndroid Build Coastguard Worker     for (i = 0; i < D3DPRESENT_BACK_BUFFERS_MAX_EX + 1; i++) {
143*61046927SAndroid Build Coastguard Worker         if (This->present_handles_pending_release[i] &&
144*61046927SAndroid Build Coastguard Worker             ID3DPresent_IsBufferReleased(This->present, This->present_handles_pending_release[i])) {
145*61046927SAndroid Build Coastguard Worker             /* WaitBufferReleased also waits the presentation feedback
146*61046927SAndroid Build Coastguard Worker              * (which should arrive at about the same time),
147*61046927SAndroid Build Coastguard Worker              * while IsBufferReleased doesn't. DestroyD3DWindowBuffer unfortunately
148*61046927SAndroid Build Coastguard Worker              * checks it to release immediately all data, else the release
149*61046927SAndroid Build Coastguard Worker              * is postponed for This->present release. To avoid leaks (we may handle
150*61046927SAndroid Build Coastguard Worker              * a lot of resize), call WaitBufferReleased. */
151*61046927SAndroid Build Coastguard Worker             ID3DPresent_WaitBufferReleased(This->present, This->present_handles_pending_release[i]);
152*61046927SAndroid Build Coastguard Worker             ID3DPresent_DestroyD3DWindowBuffer(This->present, This->present_handles_pending_release[i]);
153*61046927SAndroid Build Coastguard Worker             This->present_handles_pending_release[i] = NULL;
154*61046927SAndroid Build Coastguard Worker         }
155*61046927SAndroid Build Coastguard Worker     }
156*61046927SAndroid Build Coastguard Worker }
157*61046927SAndroid Build Coastguard Worker 
158*61046927SAndroid Build Coastguard Worker static int
159*61046927SAndroid Build Coastguard Worker NineSwapChain9_GetBackBufferCountForParams( struct NineSwapChain9 *This,
160*61046927SAndroid Build Coastguard Worker                                             D3DPRESENT_PARAMETERS *pParams );
161*61046927SAndroid Build Coastguard Worker 
162*61046927SAndroid Build Coastguard Worker HRESULT
NineSwapChain9_Resize(struct NineSwapChain9 * This,D3DPRESENT_PARAMETERS * pParams,D3DDISPLAYMODEEX * mode)163*61046927SAndroid Build Coastguard Worker NineSwapChain9_Resize( struct NineSwapChain9 *This,
164*61046927SAndroid Build Coastguard Worker                        D3DPRESENT_PARAMETERS *pParams,
165*61046927SAndroid Build Coastguard Worker                        D3DDISPLAYMODEEX *mode )
166*61046927SAndroid Build Coastguard Worker {
167*61046927SAndroid Build Coastguard Worker     struct NineDevice9 *pDevice = This->base.device;
168*61046927SAndroid Build Coastguard Worker     D3DSURFACE_DESC desc;
169*61046927SAndroid Build Coastguard Worker     HRESULT hr;
170*61046927SAndroid Build Coastguard Worker     struct pipe_resource *resource, tmplt;
171*61046927SAndroid Build Coastguard Worker     enum pipe_format pf;
172*61046927SAndroid Build Coastguard Worker     BOOL has_present_buffers = false;
173*61046927SAndroid Build Coastguard Worker     int depth;
174*61046927SAndroid Build Coastguard Worker     unsigned i, oldBufferCount, newBufferCount;
175*61046927SAndroid Build Coastguard Worker     D3DMULTISAMPLE_TYPE multisample_type;
176*61046927SAndroid Build Coastguard Worker 
177*61046927SAndroid Build Coastguard Worker     DBG("This=%p pParams=%p\n", This, pParams);
178*61046927SAndroid Build Coastguard Worker     user_assert(pParams != NULL, E_POINTER);
179*61046927SAndroid Build Coastguard Worker     user_assert(pParams->SwapEffect, D3DERR_INVALIDCALL);
180*61046927SAndroid Build Coastguard Worker     user_assert((pParams->SwapEffect != D3DSWAPEFFECT_COPY) ||
181*61046927SAndroid Build Coastguard Worker                 (pParams->BackBufferCount <= 1), D3DERR_INVALIDCALL);
182*61046927SAndroid Build Coastguard Worker     user_assert(pDevice->ex || pParams->BackBufferCount <=
183*61046927SAndroid Build Coastguard Worker                 D3DPRESENT_BACK_BUFFERS_MAX, D3DERR_INVALIDCALL);
184*61046927SAndroid Build Coastguard Worker     user_assert(!pDevice->ex || pParams->BackBufferCount <=
185*61046927SAndroid Build Coastguard Worker                 D3DPRESENT_BACK_BUFFERS_MAX_EX, D3DERR_INVALIDCALL);
186*61046927SAndroid Build Coastguard Worker     user_assert(pDevice->ex ||
187*61046927SAndroid Build Coastguard Worker                 (pParams->SwapEffect == D3DSWAPEFFECT_FLIP) ||
188*61046927SAndroid Build Coastguard Worker                 (pParams->SwapEffect == D3DSWAPEFFECT_COPY) ||
189*61046927SAndroid Build Coastguard Worker                 (pParams->SwapEffect == D3DSWAPEFFECT_DISCARD), D3DERR_INVALIDCALL);
190*61046927SAndroid Build Coastguard Worker 
191*61046927SAndroid Build Coastguard Worker     DBG("pParams(%p):\n"
192*61046927SAndroid Build Coastguard Worker         "BackBufferWidth: %u\n"
193*61046927SAndroid Build Coastguard Worker         "BackBufferHeight: %u\n"
194*61046927SAndroid Build Coastguard Worker         "BackBufferFormat: %s\n"
195*61046927SAndroid Build Coastguard Worker         "BackBufferCount: %u\n"
196*61046927SAndroid Build Coastguard Worker         "MultiSampleType: %u\n"
197*61046927SAndroid Build Coastguard Worker         "MultiSampleQuality: %u\n"
198*61046927SAndroid Build Coastguard Worker         "SwapEffect: %u\n"
199*61046927SAndroid Build Coastguard Worker         "hDeviceWindow: %p\n"
200*61046927SAndroid Build Coastguard Worker         "Windowed: %i\n"
201*61046927SAndroid Build Coastguard Worker         "EnableAutoDepthStencil: %i\n"
202*61046927SAndroid Build Coastguard Worker         "AutoDepthStencilFormat: %s\n"
203*61046927SAndroid Build Coastguard Worker         "Flags: %s\n"
204*61046927SAndroid Build Coastguard Worker         "FullScreen_RefreshRateInHz: %u\n"
205*61046927SAndroid Build Coastguard Worker         "PresentationInterval: %x\n", pParams,
206*61046927SAndroid Build Coastguard Worker         pParams->BackBufferWidth, pParams->BackBufferHeight,
207*61046927SAndroid Build Coastguard Worker         d3dformat_to_string(pParams->BackBufferFormat),
208*61046927SAndroid Build Coastguard Worker         pParams->BackBufferCount,
209*61046927SAndroid Build Coastguard Worker         pParams->MultiSampleType, pParams->MultiSampleQuality,
210*61046927SAndroid Build Coastguard Worker         pParams->SwapEffect, pParams->hDeviceWindow, pParams->Windowed,
211*61046927SAndroid Build Coastguard Worker         pParams->EnableAutoDepthStencil,
212*61046927SAndroid Build Coastguard Worker         d3dformat_to_string(pParams->AutoDepthStencilFormat),
213*61046927SAndroid Build Coastguard Worker         nine_D3DPRESENTFLAG_to_str(pParams->Flags),
214*61046927SAndroid Build Coastguard Worker         pParams->FullScreen_RefreshRateInHz,
215*61046927SAndroid Build Coastguard Worker         pParams->PresentationInterval);
216*61046927SAndroid Build Coastguard Worker 
217*61046927SAndroid Build Coastguard Worker     if (pParams->BackBufferCount == 0) {
218*61046927SAndroid Build Coastguard Worker         pParams->BackBufferCount = 1;
219*61046927SAndroid Build Coastguard Worker     }
220*61046927SAndroid Build Coastguard Worker 
221*61046927SAndroid Build Coastguard Worker     if (pParams->BackBufferFormat == D3DFMT_UNKNOWN) {
222*61046927SAndroid Build Coastguard Worker         pParams->BackBufferFormat = D3DFMT_A8R8G8B8;
223*61046927SAndroid Build Coastguard Worker     }
224*61046927SAndroid Build Coastguard Worker 
225*61046927SAndroid Build Coastguard Worker     This->desired_fences = This->actx->throttling ? This->actx->throttling_value + 1 : 0;
226*61046927SAndroid Build Coastguard Worker     /* +1 because we add the fence of the current buffer before popping an old one */
227*61046927SAndroid Build Coastguard Worker     if (This->desired_fences > DRI_SWAP_FENCES_MAX)
228*61046927SAndroid Build Coastguard Worker         This->desired_fences = DRI_SWAP_FENCES_MAX;
229*61046927SAndroid Build Coastguard Worker 
230*61046927SAndroid Build Coastguard Worker     if (This->actx->vblank_mode == 0)
231*61046927SAndroid Build Coastguard Worker         pParams->PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
232*61046927SAndroid Build Coastguard Worker     else if (This->actx->vblank_mode == 3)
233*61046927SAndroid Build Coastguard Worker         pParams->PresentationInterval = D3DPRESENT_INTERVAL_ONE;
234*61046927SAndroid Build Coastguard Worker 
235*61046927SAndroid Build Coastguard Worker     if (mode && This->mode) {
236*61046927SAndroid Build Coastguard Worker         *(This->mode) = *mode;
237*61046927SAndroid Build Coastguard Worker     } else if (mode) {
238*61046927SAndroid Build Coastguard Worker         This->mode = malloc(sizeof(D3DDISPLAYMODEEX));
239*61046927SAndroid Build Coastguard Worker         memcpy(This->mode, mode, sizeof(D3DDISPLAYMODEEX));
240*61046927SAndroid Build Coastguard Worker     } else {
241*61046927SAndroid Build Coastguard Worker         free(This->mode);
242*61046927SAndroid Build Coastguard Worker         This->mode = NULL;
243*61046927SAndroid Build Coastguard Worker     }
244*61046927SAndroid Build Coastguard Worker 
245*61046927SAndroid Build Coastguard Worker     /* Note: It is the role of the backend to fill if necessary
246*61046927SAndroid Build Coastguard Worker      * BackBufferWidth and BackBufferHeight */
247*61046927SAndroid Build Coastguard Worker     hr = ID3DPresent_SetPresentParameters(This->present, pParams, This->mode);
248*61046927SAndroid Build Coastguard Worker     if (hr != D3D_OK)
249*61046927SAndroid Build Coastguard Worker         return hr;
250*61046927SAndroid Build Coastguard Worker 
251*61046927SAndroid Build Coastguard Worker     oldBufferCount = This->num_back_buffers;
252*61046927SAndroid Build Coastguard Worker     newBufferCount = NineSwapChain9_GetBackBufferCountForParams(This, pParams);
253*61046927SAndroid Build Coastguard Worker 
254*61046927SAndroid Build Coastguard Worker     multisample_type = pParams->MultiSampleType;
255*61046927SAndroid Build Coastguard Worker 
256*61046927SAndroid Build Coastguard Worker     /* Map MultiSampleQuality to MultiSampleType */
257*61046927SAndroid Build Coastguard Worker     hr = d3dmultisample_type_check(This->screen, pParams->BackBufferFormat,
258*61046927SAndroid Build Coastguard Worker                                    &multisample_type,
259*61046927SAndroid Build Coastguard Worker                                    pParams->MultiSampleQuality,
260*61046927SAndroid Build Coastguard Worker                                    NULL);
261*61046927SAndroid Build Coastguard Worker     if (FAILED(hr)) {
262*61046927SAndroid Build Coastguard Worker         return hr;
263*61046927SAndroid Build Coastguard Worker     }
264*61046927SAndroid Build Coastguard Worker 
265*61046927SAndroid Build Coastguard Worker     pf = d3d9_to_pipe_format_checked(This->screen, pParams->BackBufferFormat,
266*61046927SAndroid Build Coastguard Worker                                      PIPE_TEXTURE_2D, multisample_type,
267*61046927SAndroid Build Coastguard Worker                                      PIPE_BIND_RENDER_TARGET, false, false);
268*61046927SAndroid Build Coastguard Worker 
269*61046927SAndroid Build Coastguard Worker     if (This->actx->linear_framebuffer ||
270*61046927SAndroid Build Coastguard Worker         (pf != PIPE_FORMAT_B8G8R8X8_UNORM &&
271*61046927SAndroid Build Coastguard Worker         pf != PIPE_FORMAT_B8G8R8A8_UNORM) ||
272*61046927SAndroid Build Coastguard Worker         pParams->SwapEffect != D3DSWAPEFFECT_DISCARD ||
273*61046927SAndroid Build Coastguard Worker         multisample_type >= 2 ||
274*61046927SAndroid Build Coastguard Worker         (This->actx->ref && This->actx->ref == This->screen))
275*61046927SAndroid Build Coastguard Worker         has_present_buffers = true;
276*61046927SAndroid Build Coastguard Worker 
277*61046927SAndroid Build Coastguard Worker     /* Note: the buffer depth has to match the window depth.
278*61046927SAndroid Build Coastguard Worker      * In practice, ARGB buffers can be used with windows
279*61046927SAndroid Build Coastguard Worker      * of depth 24. Windows of depth 32 are extremely rare.
280*61046927SAndroid Build Coastguard Worker      * So even if the buffer is ARGB, say it is depth 24.
281*61046927SAndroid Build Coastguard Worker      * It is common practice, for example that's how
282*61046927SAndroid Build Coastguard Worker      * glamor implements depth 24.
283*61046927SAndroid Build Coastguard Worker      * TODO: handle windows with other depths. Not possible in the short term.
284*61046927SAndroid Build Coastguard Worker      * For example 16 bits.*/
285*61046927SAndroid Build Coastguard Worker     depth = 24;
286*61046927SAndroid Build Coastguard Worker 
287*61046927SAndroid Build Coastguard Worker     memset(&tmplt, 0, sizeof(tmplt));
288*61046927SAndroid Build Coastguard Worker     tmplt.target = PIPE_TEXTURE_2D;
289*61046927SAndroid Build Coastguard Worker     tmplt.width0 = pParams->BackBufferWidth;
290*61046927SAndroid Build Coastguard Worker     tmplt.height0 = pParams->BackBufferHeight;
291*61046927SAndroid Build Coastguard Worker     tmplt.depth0 = 1;
292*61046927SAndroid Build Coastguard Worker     tmplt.last_level = 0;
293*61046927SAndroid Build Coastguard Worker     tmplt.array_size = 1;
294*61046927SAndroid Build Coastguard Worker     tmplt.usage = PIPE_USAGE_DEFAULT;
295*61046927SAndroid Build Coastguard Worker     tmplt.flags = 0;
296*61046927SAndroid Build Coastguard Worker 
297*61046927SAndroid Build Coastguard Worker     desc.Type = D3DRTYPE_SURFACE;
298*61046927SAndroid Build Coastguard Worker     desc.Pool = D3DPOOL_DEFAULT;
299*61046927SAndroid Build Coastguard Worker     desc.MultiSampleType = pParams->MultiSampleType;
300*61046927SAndroid Build Coastguard Worker     desc.MultiSampleQuality = pParams->MultiSampleQuality;
301*61046927SAndroid Build Coastguard Worker     desc.Width = pParams->BackBufferWidth;
302*61046927SAndroid Build Coastguard Worker     desc.Height = pParams->BackBufferHeight;
303*61046927SAndroid Build Coastguard Worker 
304*61046927SAndroid Build Coastguard Worker     for (i = 0; i < oldBufferCount; i++) {
305*61046927SAndroid Build Coastguard Worker         if (This->tasks[i])
306*61046927SAndroid Build Coastguard Worker             _mesa_threadpool_wait_for_task(This->pool, &(This->tasks[i]));
307*61046927SAndroid Build Coastguard Worker     }
308*61046927SAndroid Build Coastguard Worker     memset(This->tasks, 0, sizeof(This->tasks));
309*61046927SAndroid Build Coastguard Worker 
310*61046927SAndroid Build Coastguard Worker     if (This->pool) {
311*61046927SAndroid Build Coastguard Worker         _mesa_threadpool_destroy(This, This->pool);
312*61046927SAndroid Build Coastguard Worker         This->pool = NULL;
313*61046927SAndroid Build Coastguard Worker     }
314*61046927SAndroid Build Coastguard Worker     This->enable_threadpool = This->actx->thread_submit && (pParams->SwapEffect != D3DSWAPEFFECT_COPY);
315*61046927SAndroid Build Coastguard Worker     if (This->enable_threadpool)
316*61046927SAndroid Build Coastguard Worker         This->pool = _mesa_threadpool_create(This);
317*61046927SAndroid Build Coastguard Worker     if (!This->pool)
318*61046927SAndroid Build Coastguard Worker         This->enable_threadpool = false;
319*61046927SAndroid Build Coastguard Worker 
320*61046927SAndroid Build Coastguard Worker     for (i = 0; i < oldBufferCount; i++) {
321*61046927SAndroid Build Coastguard Worker         D3DWindowBuffer_release(This, This->present_handles[i]);
322*61046927SAndroid Build Coastguard Worker         This->present_handles[i] = NULL;
323*61046927SAndroid Build Coastguard Worker         if (This->present_buffers[i])
324*61046927SAndroid Build Coastguard Worker             pipe_resource_reference(&(This->present_buffers[i]), NULL);
325*61046927SAndroid Build Coastguard Worker     }
326*61046927SAndroid Build Coastguard Worker 
327*61046927SAndroid Build Coastguard Worker     if (newBufferCount != oldBufferCount) {
328*61046927SAndroid Build Coastguard Worker         for (i = newBufferCount; i < oldBufferCount;
329*61046927SAndroid Build Coastguard Worker              ++i)
330*61046927SAndroid Build Coastguard Worker             NineUnknown_Detach(NineUnknown(This->buffers[i]));
331*61046927SAndroid Build Coastguard Worker 
332*61046927SAndroid Build Coastguard Worker         for (i = oldBufferCount; i < newBufferCount; ++i) {
333*61046927SAndroid Build Coastguard Worker             This->buffers[i] = NULL;
334*61046927SAndroid Build Coastguard Worker             This->present_handles[i] = NULL;
335*61046927SAndroid Build Coastguard Worker         }
336*61046927SAndroid Build Coastguard Worker     }
337*61046927SAndroid Build Coastguard Worker     This->num_back_buffers = newBufferCount;
338*61046927SAndroid Build Coastguard Worker 
339*61046927SAndroid Build Coastguard Worker     for (i = 0; i < newBufferCount; ++i) {
340*61046927SAndroid Build Coastguard Worker         tmplt.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
341*61046927SAndroid Build Coastguard Worker         tmplt.nr_samples = multisample_type;
342*61046927SAndroid Build Coastguard Worker         tmplt.nr_storage_samples = multisample_type;
343*61046927SAndroid Build Coastguard Worker         if (!has_present_buffers)
344*61046927SAndroid Build Coastguard Worker             tmplt.bind |= NINE_BIND_PRESENTBUFFER_FLAGS;
345*61046927SAndroid Build Coastguard Worker         tmplt.format = d3d9_to_pipe_format_checked(This->screen,
346*61046927SAndroid Build Coastguard Worker                                                    pParams->BackBufferFormat,
347*61046927SAndroid Build Coastguard Worker                                                    PIPE_TEXTURE_2D,
348*61046927SAndroid Build Coastguard Worker                                                    tmplt.nr_samples,
349*61046927SAndroid Build Coastguard Worker                                                    tmplt.bind, false, false);
350*61046927SAndroid Build Coastguard Worker         if (tmplt.format == PIPE_FORMAT_NONE)
351*61046927SAndroid Build Coastguard Worker             return D3DERR_INVALIDCALL;
352*61046927SAndroid Build Coastguard Worker         resource = nine_resource_create_with_retry(pDevice, This->screen, &tmplt);
353*61046927SAndroid Build Coastguard Worker         if (!resource) {
354*61046927SAndroid Build Coastguard Worker             DBG("Failed to create pipe_resource.\n");
355*61046927SAndroid Build Coastguard Worker             return D3DERR_OUTOFVIDEOMEMORY;
356*61046927SAndroid Build Coastguard Worker         }
357*61046927SAndroid Build Coastguard Worker         if (pParams->Flags & D3DPRESENTFLAG_LOCKABLE_BACKBUFFER)
358*61046927SAndroid Build Coastguard Worker             resource->flags |= NINE_RESOURCE_FLAG_LOCKABLE;
359*61046927SAndroid Build Coastguard Worker         if (This->buffers[i]) {
360*61046927SAndroid Build Coastguard Worker             NineSurface9_SetMultiSampleType(This->buffers[i], desc.MultiSampleType);
361*61046927SAndroid Build Coastguard Worker             NineSurface9_SetResourceResize(This->buffers[i], resource);
362*61046927SAndroid Build Coastguard Worker             if (has_present_buffers)
363*61046927SAndroid Build Coastguard Worker                 pipe_resource_reference(&resource, NULL);
364*61046927SAndroid Build Coastguard Worker         } else {
365*61046927SAndroid Build Coastguard Worker             desc.Format = pParams->BackBufferFormat;
366*61046927SAndroid Build Coastguard Worker             desc.Usage = D3DUSAGE_RENDERTARGET;
367*61046927SAndroid Build Coastguard Worker             hr = NineSurface9_new(pDevice, NineUnknown(This), resource, NULL, 0,
368*61046927SAndroid Build Coastguard Worker                                   0, 0, &desc, &This->buffers[i]);
369*61046927SAndroid Build Coastguard Worker             if (has_present_buffers)
370*61046927SAndroid Build Coastguard Worker                 pipe_resource_reference(&resource, NULL);
371*61046927SAndroid Build Coastguard Worker             if (FAILED(hr)) {
372*61046927SAndroid Build Coastguard Worker                 DBG("Failed to create RT surface.\n");
373*61046927SAndroid Build Coastguard Worker                 return hr;
374*61046927SAndroid Build Coastguard Worker             }
375*61046927SAndroid Build Coastguard Worker             This->buffers[i]->base.base.forward = false;
376*61046927SAndroid Build Coastguard Worker         }
377*61046927SAndroid Build Coastguard Worker         if (has_present_buffers) {
378*61046927SAndroid Build Coastguard Worker             tmplt.format = PIPE_FORMAT_B8G8R8X8_UNORM;
379*61046927SAndroid Build Coastguard Worker             tmplt.bind = NINE_BIND_PRESENTBUFFER_FLAGS;
380*61046927SAndroid Build Coastguard Worker             tmplt.nr_samples = 0;
381*61046927SAndroid Build Coastguard Worker             tmplt.nr_storage_samples = 0;
382*61046927SAndroid Build Coastguard Worker             if (This->actx->linear_framebuffer)
383*61046927SAndroid Build Coastguard Worker                 tmplt.bind |= PIPE_BIND_LINEAR;
384*61046927SAndroid Build Coastguard Worker             if (pParams->SwapEffect != D3DSWAPEFFECT_DISCARD)
385*61046927SAndroid Build Coastguard Worker                 tmplt.bind |= PIPE_BIND_RENDER_TARGET;
386*61046927SAndroid Build Coastguard Worker             resource = nine_resource_create_with_retry(pDevice, This->screen, &tmplt);
387*61046927SAndroid Build Coastguard Worker             pipe_resource_reference(&(This->present_buffers[i]), resource);
388*61046927SAndroid Build Coastguard Worker         }
389*61046927SAndroid Build Coastguard Worker         This->present_handles[i] = D3DWindowBuffer_create(This, resource, depth, false);
390*61046927SAndroid Build Coastguard Worker         pipe_resource_reference(&resource, NULL);
391*61046927SAndroid Build Coastguard Worker         if (!This->present_handles[i]) {
392*61046927SAndroid Build Coastguard Worker             return D3DERR_DRIVERINTERNALERROR;
393*61046927SAndroid Build Coastguard Worker         }
394*61046927SAndroid Build Coastguard Worker     }
395*61046927SAndroid Build Coastguard Worker     if (pParams->EnableAutoDepthStencil) {
396*61046927SAndroid Build Coastguard Worker         tmplt.bind = d3d9_get_pipe_depth_format_bindings(pParams->AutoDepthStencilFormat);
397*61046927SAndroid Build Coastguard Worker         tmplt.nr_samples = multisample_type;
398*61046927SAndroid Build Coastguard Worker         tmplt.nr_storage_samples = multisample_type;
399*61046927SAndroid Build Coastguard Worker         tmplt.format = d3d9_to_pipe_format_checked(This->screen,
400*61046927SAndroid Build Coastguard Worker                                                    pParams->AutoDepthStencilFormat,
401*61046927SAndroid Build Coastguard Worker                                                    PIPE_TEXTURE_2D,
402*61046927SAndroid Build Coastguard Worker                                                    tmplt.nr_samples,
403*61046927SAndroid Build Coastguard Worker                                                    tmplt.bind,
404*61046927SAndroid Build Coastguard Worker                                                    false, false);
405*61046927SAndroid Build Coastguard Worker 
406*61046927SAndroid Build Coastguard Worker         if (tmplt.format == PIPE_FORMAT_NONE)
407*61046927SAndroid Build Coastguard Worker             return D3DERR_INVALIDCALL;
408*61046927SAndroid Build Coastguard Worker 
409*61046927SAndroid Build Coastguard Worker         if (This->zsbuf) {
410*61046927SAndroid Build Coastguard Worker             resource = nine_resource_create_with_retry(pDevice, This->screen, &tmplt);
411*61046927SAndroid Build Coastguard Worker             if (!resource) {
412*61046927SAndroid Build Coastguard Worker                 DBG("Failed to create pipe_resource for depth buffer.\n");
413*61046927SAndroid Build Coastguard Worker                 return D3DERR_OUTOFVIDEOMEMORY;
414*61046927SAndroid Build Coastguard Worker             }
415*61046927SAndroid Build Coastguard Worker 
416*61046927SAndroid Build Coastguard Worker             NineSurface9_SetMultiSampleType(This->zsbuf, desc.MultiSampleType);
417*61046927SAndroid Build Coastguard Worker             NineSurface9_SetResourceResize(This->zsbuf, resource);
418*61046927SAndroid Build Coastguard Worker             pipe_resource_reference(&resource, NULL);
419*61046927SAndroid Build Coastguard Worker         } else {
420*61046927SAndroid Build Coastguard Worker             hr = NineDevice9_CreateDepthStencilSurface(pDevice,
421*61046927SAndroid Build Coastguard Worker                                                        pParams->BackBufferWidth,
422*61046927SAndroid Build Coastguard Worker                                                        pParams->BackBufferHeight,
423*61046927SAndroid Build Coastguard Worker                                                        pParams->AutoDepthStencilFormat,
424*61046927SAndroid Build Coastguard Worker                                                        pParams->MultiSampleType,
425*61046927SAndroid Build Coastguard Worker                                                        pParams->MultiSampleQuality,
426*61046927SAndroid Build Coastguard Worker                                                        0,
427*61046927SAndroid Build Coastguard Worker                                                        (IDirect3DSurface9 **)&This->zsbuf,
428*61046927SAndroid Build Coastguard Worker                                                        NULL);
429*61046927SAndroid Build Coastguard Worker             if (FAILED(hr)) {
430*61046927SAndroid Build Coastguard Worker                 DBG("Failed to create ZS surface.\n");
431*61046927SAndroid Build Coastguard Worker                 return hr;
432*61046927SAndroid Build Coastguard Worker             }
433*61046927SAndroid Build Coastguard Worker             NineUnknown_ConvertRefToBind(NineUnknown(This->zsbuf));
434*61046927SAndroid Build Coastguard Worker         }
435*61046927SAndroid Build Coastguard Worker     }
436*61046927SAndroid Build Coastguard Worker 
437*61046927SAndroid Build Coastguard Worker     This->params = *pParams;
438*61046927SAndroid Build Coastguard Worker 
439*61046927SAndroid Build Coastguard Worker     return D3D_OK;
440*61046927SAndroid Build Coastguard Worker }
441*61046927SAndroid Build Coastguard Worker 
442*61046927SAndroid Build Coastguard Worker /* Throttling: code adapted from the dri frontend */
443*61046927SAndroid Build Coastguard Worker 
444*61046927SAndroid Build Coastguard Worker /**
445*61046927SAndroid Build Coastguard Worker  * swap_fences_pop_front - pull a fence from the throttle queue
446*61046927SAndroid Build Coastguard Worker  *
447*61046927SAndroid Build Coastguard Worker  * If the throttle queue is filled to the desired number of fences,
448*61046927SAndroid Build Coastguard Worker  * pull fences off the queue until the number is less than the desired
449*61046927SAndroid Build Coastguard Worker  * number of fences, and return the last fence pulled.
450*61046927SAndroid Build Coastguard Worker  */
451*61046927SAndroid Build Coastguard Worker static struct pipe_fence_handle *
swap_fences_pop_front(struct NineSwapChain9 * This)452*61046927SAndroid Build Coastguard Worker swap_fences_pop_front(struct NineSwapChain9 *This)
453*61046927SAndroid Build Coastguard Worker {
454*61046927SAndroid Build Coastguard Worker     struct pipe_screen *screen = This->screen;
455*61046927SAndroid Build Coastguard Worker     struct pipe_fence_handle *fence = NULL;
456*61046927SAndroid Build Coastguard Worker 
457*61046927SAndroid Build Coastguard Worker     if (This->desired_fences == 0)
458*61046927SAndroid Build Coastguard Worker         return NULL;
459*61046927SAndroid Build Coastguard Worker 
460*61046927SAndroid Build Coastguard Worker     if (This->cur_fences >= This->desired_fences) {
461*61046927SAndroid Build Coastguard Worker         screen->fence_reference(screen, &fence, This->swap_fences[This->tail]);
462*61046927SAndroid Build Coastguard Worker         screen->fence_reference(screen, &This->swap_fences[This->tail++], NULL);
463*61046927SAndroid Build Coastguard Worker         This->tail &= DRI_SWAP_FENCES_MASK;
464*61046927SAndroid Build Coastguard Worker         --This->cur_fences;
465*61046927SAndroid Build Coastguard Worker     }
466*61046927SAndroid Build Coastguard Worker     return fence;
467*61046927SAndroid Build Coastguard Worker }
468*61046927SAndroid Build Coastguard Worker 
469*61046927SAndroid Build Coastguard Worker 
470*61046927SAndroid Build Coastguard Worker /**
471*61046927SAndroid Build Coastguard Worker  * swap_fences_see_front - same than swap_fences_pop_front without
472*61046927SAndroid Build Coastguard Worker  * pulling
473*61046927SAndroid Build Coastguard Worker  *
474*61046927SAndroid Build Coastguard Worker  */
475*61046927SAndroid Build Coastguard Worker 
476*61046927SAndroid Build Coastguard Worker static struct pipe_fence_handle *
swap_fences_see_front(struct NineSwapChain9 * This)477*61046927SAndroid Build Coastguard Worker swap_fences_see_front(struct NineSwapChain9 *This)
478*61046927SAndroid Build Coastguard Worker {
479*61046927SAndroid Build Coastguard Worker     struct pipe_screen *screen = This->screen;
480*61046927SAndroid Build Coastguard Worker     struct pipe_fence_handle *fence = NULL;
481*61046927SAndroid Build Coastguard Worker 
482*61046927SAndroid Build Coastguard Worker     if (This->desired_fences == 0)
483*61046927SAndroid Build Coastguard Worker         return NULL;
484*61046927SAndroid Build Coastguard Worker 
485*61046927SAndroid Build Coastguard Worker     if (This->cur_fences >= This->desired_fences) {
486*61046927SAndroid Build Coastguard Worker         screen->fence_reference(screen, &fence, This->swap_fences[This->tail]);
487*61046927SAndroid Build Coastguard Worker     }
488*61046927SAndroid Build Coastguard Worker     return fence;
489*61046927SAndroid Build Coastguard Worker }
490*61046927SAndroid Build Coastguard Worker 
491*61046927SAndroid Build Coastguard Worker 
492*61046927SAndroid Build Coastguard Worker /**
493*61046927SAndroid Build Coastguard Worker  * swap_fences_push_back - push a fence onto the throttle queue at the back
494*61046927SAndroid Build Coastguard Worker  *
495*61046927SAndroid Build Coastguard Worker  * push a fence onto the throttle queue and pull fences of the queue
496*61046927SAndroid Build Coastguard Worker  * so that the desired number of fences are on the queue.
497*61046927SAndroid Build Coastguard Worker  */
498*61046927SAndroid Build Coastguard Worker static void
swap_fences_push_back(struct NineSwapChain9 * This,struct pipe_fence_handle * fence)499*61046927SAndroid Build Coastguard Worker swap_fences_push_back(struct NineSwapChain9 *This,
500*61046927SAndroid Build Coastguard Worker                       struct pipe_fence_handle *fence)
501*61046927SAndroid Build Coastguard Worker {
502*61046927SAndroid Build Coastguard Worker     struct pipe_screen *screen = This->screen;
503*61046927SAndroid Build Coastguard Worker 
504*61046927SAndroid Build Coastguard Worker     if (!fence || This->desired_fences == 0)
505*61046927SAndroid Build Coastguard Worker         return;
506*61046927SAndroid Build Coastguard Worker 
507*61046927SAndroid Build Coastguard Worker     while(This->cur_fences == This->desired_fences)
508*61046927SAndroid Build Coastguard Worker         swap_fences_pop_front(This);
509*61046927SAndroid Build Coastguard Worker 
510*61046927SAndroid Build Coastguard Worker     This->cur_fences++;
511*61046927SAndroid Build Coastguard Worker     screen->fence_reference(screen, &This->swap_fences[This->head++],
512*61046927SAndroid Build Coastguard Worker                             fence);
513*61046927SAndroid Build Coastguard Worker     This->head &= DRI_SWAP_FENCES_MASK;
514*61046927SAndroid Build Coastguard Worker }
515*61046927SAndroid Build Coastguard Worker 
516*61046927SAndroid Build Coastguard Worker 
517*61046927SAndroid Build Coastguard Worker /**
518*61046927SAndroid Build Coastguard Worker  * swap_fences_unref - empty the throttle queue
519*61046927SAndroid Build Coastguard Worker  *
520*61046927SAndroid Build Coastguard Worker  * pulls fences of the throttle queue until it is empty.
521*61046927SAndroid Build Coastguard Worker  */
522*61046927SAndroid Build Coastguard Worker static void
swap_fences_unref(struct NineSwapChain9 * This)523*61046927SAndroid Build Coastguard Worker swap_fences_unref(struct NineSwapChain9 *This)
524*61046927SAndroid Build Coastguard Worker {
525*61046927SAndroid Build Coastguard Worker     struct pipe_screen *screen = This->screen;
526*61046927SAndroid Build Coastguard Worker 
527*61046927SAndroid Build Coastguard Worker     while(This->cur_fences) {
528*61046927SAndroid Build Coastguard Worker         screen->fence_reference(screen, &This->swap_fences[This->tail++], NULL);
529*61046927SAndroid Build Coastguard Worker         This->tail &= DRI_SWAP_FENCES_MASK;
530*61046927SAndroid Build Coastguard Worker         --This->cur_fences;
531*61046927SAndroid Build Coastguard Worker     }
532*61046927SAndroid Build Coastguard Worker }
533*61046927SAndroid Build Coastguard Worker 
534*61046927SAndroid Build Coastguard Worker void
NineSwapChain9_dtor(struct NineSwapChain9 * This)535*61046927SAndroid Build Coastguard Worker NineSwapChain9_dtor( struct NineSwapChain9 *This )
536*61046927SAndroid Build Coastguard Worker {
537*61046927SAndroid Build Coastguard Worker     unsigned i;
538*61046927SAndroid Build Coastguard Worker 
539*61046927SAndroid Build Coastguard Worker     DBG("This=%p\n", This);
540*61046927SAndroid Build Coastguard Worker 
541*61046927SAndroid Build Coastguard Worker     if (This->pool)
542*61046927SAndroid Build Coastguard Worker         _mesa_threadpool_destroy(This, This->pool);
543*61046927SAndroid Build Coastguard Worker 
544*61046927SAndroid Build Coastguard Worker     for (i = 0; i < D3DPRESENT_BACK_BUFFERS_MAX_EX + 1; i++) {
545*61046927SAndroid Build Coastguard Worker         if (This->pending_presentation[i])
546*61046927SAndroid Build Coastguard Worker             FREE(This->pending_presentation[i]);
547*61046927SAndroid Build Coastguard Worker     }
548*61046927SAndroid Build Coastguard Worker 
549*61046927SAndroid Build Coastguard Worker     for (i = 0; i < D3DPRESENT_BACK_BUFFERS_MAX_EX + 1; i++) {
550*61046927SAndroid Build Coastguard Worker         if (This->present_handles_pending_release[i])
551*61046927SAndroid Build Coastguard Worker             ID3DPresent_DestroyD3DWindowBuffer(This->present, This->present_handles_pending_release[i]);
552*61046927SAndroid Build Coastguard Worker     }
553*61046927SAndroid Build Coastguard Worker 
554*61046927SAndroid Build Coastguard Worker     for (i = 0; i < This->num_back_buffers; i++) {
555*61046927SAndroid Build Coastguard Worker         if (This->buffers[i])
556*61046927SAndroid Build Coastguard Worker             NineUnknown_Detach(NineUnknown(This->buffers[i]));
557*61046927SAndroid Build Coastguard Worker         if (This->present_handles[i])
558*61046927SAndroid Build Coastguard Worker             ID3DPresent_DestroyD3DWindowBuffer(This->present, This->present_handles[i]);
559*61046927SAndroid Build Coastguard Worker         if (This->present_buffers[i])
560*61046927SAndroid Build Coastguard Worker             pipe_resource_reference(&(This->present_buffers[i]), NULL);
561*61046927SAndroid Build Coastguard Worker     }
562*61046927SAndroid Build Coastguard Worker     if (This->zsbuf)
563*61046927SAndroid Build Coastguard Worker         NineUnknown_Unbind(NineUnknown(This->zsbuf));
564*61046927SAndroid Build Coastguard Worker 
565*61046927SAndroid Build Coastguard Worker     if (This->present)
566*61046927SAndroid Build Coastguard Worker         ID3DPresent_Release(This->present);
567*61046927SAndroid Build Coastguard Worker 
568*61046927SAndroid Build Coastguard Worker     swap_fences_unref(This);
569*61046927SAndroid Build Coastguard Worker     NineUnknown_dtor(&This->base);
570*61046927SAndroid Build Coastguard Worker }
571*61046927SAndroid Build Coastguard Worker 
572*61046927SAndroid Build Coastguard Worker static void
create_present_buffer(struct NineSwapChain9 * This,unsigned int width,unsigned int height,struct pipe_resource ** resource,D3DWindowBuffer ** present_handle)573*61046927SAndroid Build Coastguard Worker create_present_buffer( struct NineSwapChain9 *This,
574*61046927SAndroid Build Coastguard Worker                        unsigned int width, unsigned int height,
575*61046927SAndroid Build Coastguard Worker                        struct pipe_resource **resource,
576*61046927SAndroid Build Coastguard Worker                        D3DWindowBuffer **present_handle)
577*61046927SAndroid Build Coastguard Worker {
578*61046927SAndroid Build Coastguard Worker     struct pipe_resource tmplt;
579*61046927SAndroid Build Coastguard Worker 
580*61046927SAndroid Build Coastguard Worker     memset(&tmplt, 0, sizeof(tmplt));
581*61046927SAndroid Build Coastguard Worker     tmplt.target = PIPE_TEXTURE_2D;
582*61046927SAndroid Build Coastguard Worker     tmplt.width0 = width;
583*61046927SAndroid Build Coastguard Worker     tmplt.height0 = height;
584*61046927SAndroid Build Coastguard Worker     tmplt.depth0 = 1;
585*61046927SAndroid Build Coastguard Worker     tmplt.last_level = 0;
586*61046927SAndroid Build Coastguard Worker     tmplt.array_size = 1;
587*61046927SAndroid Build Coastguard Worker     tmplt.usage = PIPE_USAGE_DEFAULT;
588*61046927SAndroid Build Coastguard Worker     tmplt.flags = 0;
589*61046927SAndroid Build Coastguard Worker     tmplt.format = PIPE_FORMAT_B8G8R8X8_UNORM;
590*61046927SAndroid Build Coastguard Worker     tmplt.bind = NINE_BIND_BACKBUFFER_FLAGS |
591*61046927SAndroid Build Coastguard Worker                  NINE_BIND_PRESENTBUFFER_FLAGS;
592*61046927SAndroid Build Coastguard Worker     tmplt.nr_samples = 0;
593*61046927SAndroid Build Coastguard Worker     if (This->actx->linear_framebuffer)
594*61046927SAndroid Build Coastguard Worker         tmplt.bind |= PIPE_BIND_LINEAR;
595*61046927SAndroid Build Coastguard Worker     *resource = nine_resource_create_with_retry(This->base.device, This->screen, &tmplt);
596*61046927SAndroid Build Coastguard Worker 
597*61046927SAndroid Build Coastguard Worker     *present_handle = D3DWindowBuffer_create(This, *resource, 24, true);
598*61046927SAndroid Build Coastguard Worker 
599*61046927SAndroid Build Coastguard Worker     if (!*present_handle) {
600*61046927SAndroid Build Coastguard Worker         pipe_resource_reference(resource, NULL);
601*61046927SAndroid Build Coastguard Worker     }
602*61046927SAndroid Build Coastguard Worker }
603*61046927SAndroid Build Coastguard Worker 
604*61046927SAndroid Build Coastguard Worker static void
handle_draw_cursor_and_hud(struct NineSwapChain9 * This,struct pipe_resource * resource)605*61046927SAndroid Build Coastguard Worker handle_draw_cursor_and_hud( struct NineSwapChain9 *This, struct pipe_resource *resource)
606*61046927SAndroid Build Coastguard Worker {
607*61046927SAndroid Build Coastguard Worker     struct NineDevice9 *device = This->base.device;
608*61046927SAndroid Build Coastguard Worker     struct pipe_blit_info blit;
609*61046927SAndroid Build Coastguard Worker     struct pipe_context *pipe;
610*61046927SAndroid Build Coastguard Worker 
611*61046927SAndroid Build Coastguard Worker     if (device->cursor.software && device->cursor.visible && device->cursor.w) {
612*61046927SAndroid Build Coastguard Worker         memset(&blit, 0, sizeof(blit));
613*61046927SAndroid Build Coastguard Worker         blit.src.resource = device->cursor.image;
614*61046927SAndroid Build Coastguard Worker         blit.src.level = 0;
615*61046927SAndroid Build Coastguard Worker         blit.src.format = device->cursor.image->format;
616*61046927SAndroid Build Coastguard Worker         blit.src.box.x = 0;
617*61046927SAndroid Build Coastguard Worker         blit.src.box.y = 0;
618*61046927SAndroid Build Coastguard Worker         blit.src.box.z = 0;
619*61046927SAndroid Build Coastguard Worker         blit.src.box.depth = 1;
620*61046927SAndroid Build Coastguard Worker         blit.src.box.width = device->cursor.w;
621*61046927SAndroid Build Coastguard Worker         blit.src.box.height = device->cursor.h;
622*61046927SAndroid Build Coastguard Worker 
623*61046927SAndroid Build Coastguard Worker         blit.dst.resource = resource;
624*61046927SAndroid Build Coastguard Worker         blit.dst.level = 0;
625*61046927SAndroid Build Coastguard Worker         blit.dst.format = resource->format;
626*61046927SAndroid Build Coastguard Worker         blit.dst.box.z = 0;
627*61046927SAndroid Build Coastguard Worker         blit.dst.box.depth = 1;
628*61046927SAndroid Build Coastguard Worker 
629*61046927SAndroid Build Coastguard Worker         blit.mask = PIPE_MASK_RGBA;
630*61046927SAndroid Build Coastguard Worker         blit.filter = PIPE_TEX_FILTER_NEAREST;
631*61046927SAndroid Build Coastguard Worker         blit.scissor_enable = false;
632*61046927SAndroid Build Coastguard Worker 
633*61046927SAndroid Build Coastguard Worker         /* NOTE: blit messes up when box.x + box.width < 0, fix driver
634*61046927SAndroid Build Coastguard Worker          * NOTE2: device->cursor.pos contains coordinates relative to the screen.
635*61046927SAndroid Build Coastguard Worker          * This happens to be also the position of the cursor when we are fullscreen.
636*61046927SAndroid Build Coastguard Worker          * We don't use sw cursor for Windowed mode */
637*61046927SAndroid Build Coastguard Worker         blit.dst.box.x = MAX2(device->cursor.pos.x, 0) - device->cursor.hotspot.x;
638*61046927SAndroid Build Coastguard Worker         blit.dst.box.y = MAX2(device->cursor.pos.y, 0) - device->cursor.hotspot.y;
639*61046927SAndroid Build Coastguard Worker         blit.dst.box.width = blit.src.box.width;
640*61046927SAndroid Build Coastguard Worker         blit.dst.box.height = blit.src.box.height;
641*61046927SAndroid Build Coastguard Worker 
642*61046927SAndroid Build Coastguard Worker         DBG("Blitting cursor(%ux%u) to (%i,%i).\n",
643*61046927SAndroid Build Coastguard Worker             blit.src.box.width, blit.src.box.height,
644*61046927SAndroid Build Coastguard Worker             blit.dst.box.x, blit.dst.box.y);
645*61046927SAndroid Build Coastguard Worker 
646*61046927SAndroid Build Coastguard Worker         blit.alpha_blend = true;
647*61046927SAndroid Build Coastguard Worker         pipe = NineDevice9_GetPipe(This->base.device);
648*61046927SAndroid Build Coastguard Worker         pipe->blit(pipe, &blit);
649*61046927SAndroid Build Coastguard Worker     }
650*61046927SAndroid Build Coastguard Worker 
651*61046927SAndroid Build Coastguard Worker     if (device->hud && resource) {
652*61046927SAndroid Build Coastguard Worker         /* Implicit use of context pipe */
653*61046927SAndroid Build Coastguard Worker         (void)NineDevice9_GetPipe(This->base.device);
654*61046927SAndroid Build Coastguard Worker         hud_run(device->hud, NULL, resource); /* XXX: no offset */
655*61046927SAndroid Build Coastguard Worker         /* HUD doesn't clobber stipple */
656*61046927SAndroid Build Coastguard Worker         nine_state_restore_non_cso(device);
657*61046927SAndroid Build Coastguard Worker     }
658*61046927SAndroid Build Coastguard Worker }
659*61046927SAndroid Build Coastguard Worker 
660*61046927SAndroid Build Coastguard Worker struct end_present_struct {
661*61046927SAndroid Build Coastguard Worker     struct pipe_screen *screen;
662*61046927SAndroid Build Coastguard Worker     struct pipe_fence_handle *fence_to_wait;
663*61046927SAndroid Build Coastguard Worker     ID3DPresent *present;
664*61046927SAndroid Build Coastguard Worker     D3DWindowBuffer *present_handle;
665*61046927SAndroid Build Coastguard Worker     BOOL *pending_presentation;
666*61046927SAndroid Build Coastguard Worker     HWND hDestWindowOverride;
667*61046927SAndroid Build Coastguard Worker };
668*61046927SAndroid Build Coastguard Worker 
work_present(void * data)669*61046927SAndroid Build Coastguard Worker static void work_present(void *data)
670*61046927SAndroid Build Coastguard Worker {
671*61046927SAndroid Build Coastguard Worker     struct end_present_struct *work = data;
672*61046927SAndroid Build Coastguard Worker     if (work->fence_to_wait) {
673*61046927SAndroid Build Coastguard Worker         (void) work->screen->fence_finish(work->screen, NULL, work->fence_to_wait, OS_TIMEOUT_INFINITE);
674*61046927SAndroid Build Coastguard Worker         work->screen->fence_reference(work->screen, &(work->fence_to_wait), NULL);
675*61046927SAndroid Build Coastguard Worker     }
676*61046927SAndroid Build Coastguard Worker     ID3DPresent_PresentBuffer(work->present, work->present_handle, work->hDestWindowOverride, NULL, NULL, NULL, 0);
677*61046927SAndroid Build Coastguard Worker     p_atomic_set(work->pending_presentation, false);
678*61046927SAndroid Build Coastguard Worker     free(work);
679*61046927SAndroid Build Coastguard Worker }
680*61046927SAndroid Build Coastguard Worker 
pend_present(struct NineSwapChain9 * This,struct pipe_fence_handle * fence,HWND hDestWindowOverride)681*61046927SAndroid Build Coastguard Worker static void pend_present(struct NineSwapChain9 *This,
682*61046927SAndroid Build Coastguard Worker                          struct pipe_fence_handle *fence,
683*61046927SAndroid Build Coastguard Worker                          HWND hDestWindowOverride)
684*61046927SAndroid Build Coastguard Worker {
685*61046927SAndroid Build Coastguard Worker     struct end_present_struct *work = calloc(1, sizeof(struct end_present_struct));
686*61046927SAndroid Build Coastguard Worker 
687*61046927SAndroid Build Coastguard Worker     work->screen = This->screen;
688*61046927SAndroid Build Coastguard Worker     This->screen->fence_reference(This->screen, &work->fence_to_wait, fence);
689*61046927SAndroid Build Coastguard Worker     work->present = This->present;
690*61046927SAndroid Build Coastguard Worker     work->present_handle = This->present_handles[0];
691*61046927SAndroid Build Coastguard Worker     work->hDestWindowOverride = hDestWindowOverride;
692*61046927SAndroid Build Coastguard Worker     work->pending_presentation = This->pending_presentation[0];
693*61046927SAndroid Build Coastguard Worker     p_atomic_set(work->pending_presentation, true);
694*61046927SAndroid Build Coastguard Worker     This->tasks[0] = _mesa_threadpool_queue_task(This->pool, work_present, work);
695*61046927SAndroid Build Coastguard Worker 
696*61046927SAndroid Build Coastguard Worker     return;
697*61046927SAndroid Build Coastguard Worker }
698*61046927SAndroid Build Coastguard Worker 
699*61046927SAndroid Build Coastguard Worker static inline HRESULT
present(struct NineSwapChain9 * This,const RECT * pSourceRect,const RECT * pDestRect,HWND hDestWindowOverride,const RGNDATA * pDirtyRegion,DWORD dwFlags)700*61046927SAndroid Build Coastguard Worker present( struct NineSwapChain9 *This,
701*61046927SAndroid Build Coastguard Worker          const RECT *pSourceRect,
702*61046927SAndroid Build Coastguard Worker          const RECT *pDestRect,
703*61046927SAndroid Build Coastguard Worker          HWND hDestWindowOverride,
704*61046927SAndroid Build Coastguard Worker          const RGNDATA *pDirtyRegion,
705*61046927SAndroid Build Coastguard Worker          DWORD dwFlags )
706*61046927SAndroid Build Coastguard Worker {
707*61046927SAndroid Build Coastguard Worker     struct pipe_context *pipe;
708*61046927SAndroid Build Coastguard Worker     struct pipe_resource *resource;
709*61046927SAndroid Build Coastguard Worker     struct pipe_fence_handle *fence;
710*61046927SAndroid Build Coastguard Worker     HRESULT hr;
711*61046927SAndroid Build Coastguard Worker     struct pipe_blit_info blit;
712*61046927SAndroid Build Coastguard Worker     int target_width, target_height, target_depth, i;
713*61046927SAndroid Build Coastguard Worker     RECT source_rect;
714*61046927SAndroid Build Coastguard Worker     RECT dest_rect;
715*61046927SAndroid Build Coastguard Worker 
716*61046927SAndroid Build Coastguard Worker     DBG("present: This=%p pSourceRect=%p pDestRect=%p "
717*61046927SAndroid Build Coastguard Worker         "pDirtyRegion=%p hDestWindowOverride=%p"
718*61046927SAndroid Build Coastguard Worker         "dwFlags=%d resource=%p\n",
719*61046927SAndroid Build Coastguard Worker         This, pSourceRect, pDestRect, pDirtyRegion,
720*61046927SAndroid Build Coastguard Worker         hDestWindowOverride, (int)dwFlags, This->buffers[0]->base.resource);
721*61046927SAndroid Build Coastguard Worker 
722*61046927SAndroid Build Coastguard Worker     /* We can choose to only update pDirtyRegion, but the backend can choose
723*61046927SAndroid Build Coastguard Worker      * to update everything. Let's ignore */
724*61046927SAndroid Build Coastguard Worker     (void) pDirtyRegion;
725*61046927SAndroid Build Coastguard Worker 
726*61046927SAndroid Build Coastguard Worker     resource = This->buffers[0]->base.resource;
727*61046927SAndroid Build Coastguard Worker 
728*61046927SAndroid Build Coastguard Worker     if (pSourceRect) {
729*61046927SAndroid Build Coastguard Worker         DBG("pSourceRect = (%u..%u)x(%u..%u)\n",
730*61046927SAndroid Build Coastguard Worker             pSourceRect->left, pSourceRect->right,
731*61046927SAndroid Build Coastguard Worker             pSourceRect->top, pSourceRect->bottom);
732*61046927SAndroid Build Coastguard Worker         source_rect = *pSourceRect;
733*61046927SAndroid Build Coastguard Worker         if (source_rect.top == 0 &&
734*61046927SAndroid Build Coastguard Worker             source_rect.left == 0 &&
735*61046927SAndroid Build Coastguard Worker             source_rect.bottom == resource->height0 &&
736*61046927SAndroid Build Coastguard Worker             source_rect.right == resource->width0)
737*61046927SAndroid Build Coastguard Worker             pSourceRect = NULL;
738*61046927SAndroid Build Coastguard Worker         /* TODO: Handle more of pSourceRect.
739*61046927SAndroid Build Coastguard Worker          * Currently we should support:
740*61046927SAndroid Build Coastguard Worker          * . When there is no pSourceRect
741*61046927SAndroid Build Coastguard Worker          * . When pSourceRect is the full buffer.
742*61046927SAndroid Build Coastguard Worker          */
743*61046927SAndroid Build Coastguard Worker     }
744*61046927SAndroid Build Coastguard Worker     if (pDestRect) {
745*61046927SAndroid Build Coastguard Worker         DBG("pDestRect = (%u..%u)x(%u..%u)\n",
746*61046927SAndroid Build Coastguard Worker             pDestRect->left, pDestRect->right,
747*61046927SAndroid Build Coastguard Worker             pDestRect->top, pDestRect->bottom);
748*61046927SAndroid Build Coastguard Worker         dest_rect = *pDestRect;
749*61046927SAndroid Build Coastguard Worker     }
750*61046927SAndroid Build Coastguard Worker 
751*61046927SAndroid Build Coastguard Worker     if (This->rendering_done)
752*61046927SAndroid Build Coastguard Worker         goto bypass_rendering;
753*61046927SAndroid Build Coastguard Worker 
754*61046927SAndroid Build Coastguard Worker     if (This->params.SwapEffect == D3DSWAPEFFECT_DISCARD)
755*61046927SAndroid Build Coastguard Worker         handle_draw_cursor_and_hud(This, resource);
756*61046927SAndroid Build Coastguard Worker 
757*61046927SAndroid Build Coastguard Worker     hr = ID3DPresent_GetWindowInfo(This->present, hDestWindowOverride, &target_width, &target_height, &target_depth);
758*61046927SAndroid Build Coastguard Worker     (void)target_depth;
759*61046927SAndroid Build Coastguard Worker 
760*61046927SAndroid Build Coastguard Worker     /* Can happen with old Wine (presentation can still succeed),
761*61046927SAndroid Build Coastguard Worker      * or at window destruction.
762*61046927SAndroid Build Coastguard Worker      * Also disable for very old wine as D3DWindowBuffer_release
763*61046927SAndroid Build Coastguard Worker      * cannot do the DestroyD3DWindowBuffer workaround. */
764*61046927SAndroid Build Coastguard Worker     if (FAILED(hr) || target_width == 0 || target_height == 0 ||
765*61046927SAndroid Build Coastguard Worker         This->base.device->minor_version_num <= 2) {
766*61046927SAndroid Build Coastguard Worker         target_width = resource->width0;
767*61046927SAndroid Build Coastguard Worker         target_height = resource->height0;
768*61046927SAndroid Build Coastguard Worker     }
769*61046927SAndroid Build Coastguard Worker 
770*61046927SAndroid Build Coastguard Worker     if (pDestRect) {
771*61046927SAndroid Build Coastguard Worker         dest_rect.top = MAX2(0, dest_rect.top);
772*61046927SAndroid Build Coastguard Worker         dest_rect.left = MAX2(0, dest_rect.left);
773*61046927SAndroid Build Coastguard Worker         dest_rect.bottom = MIN2(target_height, dest_rect.bottom);
774*61046927SAndroid Build Coastguard Worker         dest_rect.right = MIN2(target_width, dest_rect.right);
775*61046927SAndroid Build Coastguard Worker         target_height = dest_rect.bottom - dest_rect.top;
776*61046927SAndroid Build Coastguard Worker         target_width = dest_rect.right - dest_rect.left;
777*61046927SAndroid Build Coastguard Worker     }
778*61046927SAndroid Build Coastguard Worker 
779*61046927SAndroid Build Coastguard Worker     /* Switch to using presentation buffers on window resize.
780*61046927SAndroid Build Coastguard Worker      * Note: Most apps should resize the d3d back buffers when
781*61046927SAndroid Build Coastguard Worker      * a window resize is detected, which will result in a call to
782*61046927SAndroid Build Coastguard Worker      * NineSwapChain9_Resize. Thus everything will get released,
783*61046927SAndroid Build Coastguard Worker      * and it will switch back to not using separate presentation
784*61046927SAndroid Build Coastguard Worker      * buffers. */
785*61046927SAndroid Build Coastguard Worker     if (!This->present_buffers[0] &&
786*61046927SAndroid Build Coastguard Worker         (target_width != resource->width0 || target_height != resource->height0)) {
787*61046927SAndroid Build Coastguard Worker         BOOL failure = false;
788*61046927SAndroid Build Coastguard Worker         struct pipe_resource *new_resource[This->num_back_buffers];
789*61046927SAndroid Build Coastguard Worker         D3DWindowBuffer *new_handles[This->num_back_buffers];
790*61046927SAndroid Build Coastguard Worker         for (i = 0; i < This->num_back_buffers; i++) {
791*61046927SAndroid Build Coastguard Worker             /* Note: if (!new_handles[i]), new_resource[i]
792*61046927SAndroid Build Coastguard Worker              * gets released and contains NULL */
793*61046927SAndroid Build Coastguard Worker             create_present_buffer(This, target_width, target_height, &new_resource[i], &new_handles[i]);
794*61046927SAndroid Build Coastguard Worker             if (!new_handles[i])
795*61046927SAndroid Build Coastguard Worker                 failure = true;
796*61046927SAndroid Build Coastguard Worker         }
797*61046927SAndroid Build Coastguard Worker         if (failure) {
798*61046927SAndroid Build Coastguard Worker             for (i = 0; i < This->num_back_buffers; i++) {
799*61046927SAndroid Build Coastguard Worker                 if (new_resource[i])
800*61046927SAndroid Build Coastguard Worker                     pipe_resource_reference(&new_resource[i], NULL);
801*61046927SAndroid Build Coastguard Worker                 if (new_handles[i])
802*61046927SAndroid Build Coastguard Worker                     D3DWindowBuffer_release(This, new_handles[i]);
803*61046927SAndroid Build Coastguard Worker             }
804*61046927SAndroid Build Coastguard Worker         } else {
805*61046927SAndroid Build Coastguard Worker             for (i = 0; i < This->num_back_buffers; i++) {
806*61046927SAndroid Build Coastguard Worker                 D3DWindowBuffer_release(This, This->present_handles[i]);
807*61046927SAndroid Build Coastguard Worker                 This->present_handles[i] = new_handles[i];
808*61046927SAndroid Build Coastguard Worker                 pipe_resource_reference(&This->present_buffers[i], new_resource[i]);
809*61046927SAndroid Build Coastguard Worker                 pipe_resource_reference(&new_resource[i], NULL);
810*61046927SAndroid Build Coastguard Worker             }
811*61046927SAndroid Build Coastguard Worker         }
812*61046927SAndroid Build Coastguard Worker     }
813*61046927SAndroid Build Coastguard Worker 
814*61046927SAndroid Build Coastguard Worker     pipe = NineDevice9_GetPipe(This->base.device);
815*61046927SAndroid Build Coastguard Worker 
816*61046927SAndroid Build Coastguard Worker     if (This->present_buffers[0]) {
817*61046927SAndroid Build Coastguard Worker         memset(&blit, 0, sizeof(blit));
818*61046927SAndroid Build Coastguard Worker         blit.src.resource = resource;
819*61046927SAndroid Build Coastguard Worker         blit.src.level = 0; /* Note: This->buffers[0]->level should always be 0 */
820*61046927SAndroid Build Coastguard Worker         blit.src.format = resource->format;
821*61046927SAndroid Build Coastguard Worker         blit.src.box.z = 0;
822*61046927SAndroid Build Coastguard Worker         blit.src.box.depth = 1;
823*61046927SAndroid Build Coastguard Worker         blit.src.box.x = 0;
824*61046927SAndroid Build Coastguard Worker         blit.src.box.y = 0;
825*61046927SAndroid Build Coastguard Worker         blit.src.box.width = resource->width0;
826*61046927SAndroid Build Coastguard Worker         blit.src.box.height = resource->height0;
827*61046927SAndroid Build Coastguard Worker 
828*61046927SAndroid Build Coastguard Worker         /* Reallocate a new presentation buffer if the target window
829*61046927SAndroid Build Coastguard Worker          * size has changed */
830*61046927SAndroid Build Coastguard Worker         if (target_width != This->present_buffers[0]->width0 ||
831*61046927SAndroid Build Coastguard Worker             target_height != This->present_buffers[0]->height0) {
832*61046927SAndroid Build Coastguard Worker             struct pipe_resource *new_resource;
833*61046927SAndroid Build Coastguard Worker             D3DWindowBuffer *new_handle;
834*61046927SAndroid Build Coastguard Worker 
835*61046927SAndroid Build Coastguard Worker             create_present_buffer(This, target_width, target_height, &new_resource, &new_handle);
836*61046927SAndroid Build Coastguard Worker             /* Switch to the new buffer */
837*61046927SAndroid Build Coastguard Worker             if (new_handle) {
838*61046927SAndroid Build Coastguard Worker                 D3DWindowBuffer_release(This, This->present_handles[0]);
839*61046927SAndroid Build Coastguard Worker                 This->present_handles[0] = new_handle;
840*61046927SAndroid Build Coastguard Worker                 pipe_resource_reference(&This->present_buffers[0], new_resource);
841*61046927SAndroid Build Coastguard Worker                 pipe_resource_reference(&new_resource, NULL);
842*61046927SAndroid Build Coastguard Worker             }
843*61046927SAndroid Build Coastguard Worker         }
844*61046927SAndroid Build Coastguard Worker 
845*61046927SAndroid Build Coastguard Worker         resource = This->present_buffers[0];
846*61046927SAndroid Build Coastguard Worker 
847*61046927SAndroid Build Coastguard Worker         blit.dst.resource = resource;
848*61046927SAndroid Build Coastguard Worker         blit.dst.level = 0;
849*61046927SAndroid Build Coastguard Worker         blit.dst.format = resource->format;
850*61046927SAndroid Build Coastguard Worker         blit.dst.box.z = 0;
851*61046927SAndroid Build Coastguard Worker         blit.dst.box.depth = 1;
852*61046927SAndroid Build Coastguard Worker         blit.dst.box.x = 0;
853*61046927SAndroid Build Coastguard Worker         blit.dst.box.y = 0;
854*61046927SAndroid Build Coastguard Worker         blit.dst.box.width = resource->width0;
855*61046927SAndroid Build Coastguard Worker         blit.dst.box.height = resource->height0;
856*61046927SAndroid Build Coastguard Worker 
857*61046927SAndroid Build Coastguard Worker         blit.mask = PIPE_MASK_RGBA;
858*61046927SAndroid Build Coastguard Worker         blit.filter = (blit.dst.box.width == blit.src.box.width &&
859*61046927SAndroid Build Coastguard Worker                        blit.dst.box.height == blit.src.box.height) ?
860*61046927SAndroid Build Coastguard Worker                           PIPE_TEX_FILTER_NEAREST : PIPE_TEX_FILTER_LINEAR;
861*61046927SAndroid Build Coastguard Worker         blit.scissor_enable = false;
862*61046927SAndroid Build Coastguard Worker         blit.alpha_blend = false;
863*61046927SAndroid Build Coastguard Worker 
864*61046927SAndroid Build Coastguard Worker         pipe->blit(pipe, &blit);
865*61046927SAndroid Build Coastguard Worker     }
866*61046927SAndroid Build Coastguard Worker 
867*61046927SAndroid Build Coastguard Worker     /* The resource we present has to resolve fast clears
868*61046927SAndroid Build Coastguard Worker      * if needed (and other things) */
869*61046927SAndroid Build Coastguard Worker     pipe->flush_resource(pipe, resource);
870*61046927SAndroid Build Coastguard Worker 
871*61046927SAndroid Build Coastguard Worker     if (This->params.SwapEffect != D3DSWAPEFFECT_DISCARD)
872*61046927SAndroid Build Coastguard Worker         handle_draw_cursor_and_hud(This, resource);
873*61046927SAndroid Build Coastguard Worker 
874*61046927SAndroid Build Coastguard Worker     fence = NULL;
875*61046927SAndroid Build Coastguard Worker     /* When threadpool is enabled, we don't submit before the fence
876*61046927SAndroid Build Coastguard Worker      * tells us rendering was finished, thus we can flush async there */
877*61046927SAndroid Build Coastguard Worker     pipe->flush(pipe, &fence, PIPE_FLUSH_END_OF_FRAME | (This->enable_threadpool ? PIPE_FLUSH_ASYNC : 0));
878*61046927SAndroid Build Coastguard Worker 
879*61046927SAndroid Build Coastguard Worker     /* Present now for thread_submit, because we have the fence.
880*61046927SAndroid Build Coastguard Worker      * It's possible we return WASSTILLDRAWING and still Present,
881*61046927SAndroid Build Coastguard Worker      * but it should be fine. */
882*61046927SAndroid Build Coastguard Worker     if (This->enable_threadpool)
883*61046927SAndroid Build Coastguard Worker         pend_present(This, fence, hDestWindowOverride);
884*61046927SAndroid Build Coastguard Worker     if (fence) {
885*61046927SAndroid Build Coastguard Worker         swap_fences_push_back(This, fence);
886*61046927SAndroid Build Coastguard Worker         This->screen->fence_reference(This->screen, &fence, NULL);
887*61046927SAndroid Build Coastguard Worker     }
888*61046927SAndroid Build Coastguard Worker 
889*61046927SAndroid Build Coastguard Worker     This->rendering_done = true;
890*61046927SAndroid Build Coastguard Worker bypass_rendering:
891*61046927SAndroid Build Coastguard Worker 
892*61046927SAndroid Build Coastguard Worker     if (dwFlags & D3DPRESENT_DONOTWAIT) {
893*61046927SAndroid Build Coastguard Worker         UNTESTED(2);
894*61046927SAndroid Build Coastguard Worker         BOOL still_draw = false;
895*61046927SAndroid Build Coastguard Worker         fence = swap_fences_see_front(This);
896*61046927SAndroid Build Coastguard Worker         if (fence) {
897*61046927SAndroid Build Coastguard Worker             still_draw = !This->screen->fence_finish(This->screen, NULL, fence, 0);
898*61046927SAndroid Build Coastguard Worker             This->screen->fence_reference(This->screen, &fence, NULL);
899*61046927SAndroid Build Coastguard Worker         }
900*61046927SAndroid Build Coastguard Worker         if (still_draw)
901*61046927SAndroid Build Coastguard Worker             return D3DERR_WASSTILLDRAWING;
902*61046927SAndroid Build Coastguard Worker     }
903*61046927SAndroid Build Coastguard Worker 
904*61046927SAndroid Build Coastguard Worker     /* Throttle rendering if needed */
905*61046927SAndroid Build Coastguard Worker     fence = swap_fences_pop_front(This);
906*61046927SAndroid Build Coastguard Worker     if (fence) {
907*61046927SAndroid Build Coastguard Worker         (void) This->screen->fence_finish(This->screen, NULL, fence, OS_TIMEOUT_INFINITE);
908*61046927SAndroid Build Coastguard Worker         This->screen->fence_reference(This->screen, &fence, NULL);
909*61046927SAndroid Build Coastguard Worker     }
910*61046927SAndroid Build Coastguard Worker 
911*61046927SAndroid Build Coastguard Worker     This->rendering_done = false;
912*61046927SAndroid Build Coastguard Worker 
913*61046927SAndroid Build Coastguard Worker     if (!This->enable_threadpool) {
914*61046927SAndroid Build Coastguard Worker         This->tasks[0]=NULL;
915*61046927SAndroid Build Coastguard Worker 
916*61046927SAndroid Build Coastguard Worker         hr = ID3DPresent_PresentBuffer(This->present, This->present_handles[0], hDestWindowOverride, pSourceRect, pDestRect ? &dest_rect : NULL, NULL, dwFlags);
917*61046927SAndroid Build Coastguard Worker 
918*61046927SAndroid Build Coastguard Worker         if (FAILED(hr)) { UNTESTED(3);return hr; }
919*61046927SAndroid Build Coastguard Worker     }
920*61046927SAndroid Build Coastguard Worker 
921*61046927SAndroid Build Coastguard Worker     This->base.device->end_scene_since_present = 0;
922*61046927SAndroid Build Coastguard Worker     This->base.device->frame_count++;
923*61046927SAndroid Build Coastguard Worker     return D3D_OK;
924*61046927SAndroid Build Coastguard Worker }
925*61046927SAndroid Build Coastguard Worker 
926*61046927SAndroid Build Coastguard Worker HRESULT NINE_WINAPI
NineSwapChain9_Present(struct NineSwapChain9 * This,const RECT * pSourceRect,const RECT * pDestRect,HWND hDestWindowOverride,const RGNDATA * pDirtyRegion,DWORD dwFlags)927*61046927SAndroid Build Coastguard Worker NineSwapChain9_Present( struct NineSwapChain9 *This,
928*61046927SAndroid Build Coastguard Worker                         const RECT *pSourceRect,
929*61046927SAndroid Build Coastguard Worker                         const RECT *pDestRect,
930*61046927SAndroid Build Coastguard Worker                         HWND hDestWindowOverride,
931*61046927SAndroid Build Coastguard Worker                         const RGNDATA *pDirtyRegion,
932*61046927SAndroid Build Coastguard Worker                         DWORD dwFlags )
933*61046927SAndroid Build Coastguard Worker {
934*61046927SAndroid Build Coastguard Worker     struct pipe_resource *res = NULL;
935*61046927SAndroid Build Coastguard Worker     D3DWindowBuffer *handle_temp;
936*61046927SAndroid Build Coastguard Worker     struct threadpool_task *task_temp;
937*61046927SAndroid Build Coastguard Worker     BOOL *pending_presentation_temp;
938*61046927SAndroid Build Coastguard Worker     int i;
939*61046927SAndroid Build Coastguard Worker     HRESULT hr;
940*61046927SAndroid Build Coastguard Worker 
941*61046927SAndroid Build Coastguard Worker     DBG("This=%p pSourceRect=%p pDestRect=%p hDestWindowOverride=%p "
942*61046927SAndroid Build Coastguard Worker         "pDirtyRegion=%p dwFlags=%d\n",
943*61046927SAndroid Build Coastguard Worker         This, pSourceRect, pDestRect, hDestWindowOverride,
944*61046927SAndroid Build Coastguard Worker         pDirtyRegion,dwFlags);
945*61046927SAndroid Build Coastguard Worker 
946*61046927SAndroid Build Coastguard Worker     if (This->base.device->ex) {
947*61046927SAndroid Build Coastguard Worker         if (NineSwapChain9_GetOccluded(This)) {
948*61046927SAndroid Build Coastguard Worker             DBG("Present is occluded. Returning S_PRESENT_OCCLUDED.\n");
949*61046927SAndroid Build Coastguard Worker             return S_PRESENT_OCCLUDED;
950*61046927SAndroid Build Coastguard Worker         }
951*61046927SAndroid Build Coastguard Worker     } else {
952*61046927SAndroid Build Coastguard Worker         if (NineSwapChain9_GetOccluded(This) ||
953*61046927SAndroid Build Coastguard Worker             NineSwapChain9_ResolutionMismatch(This)) {
954*61046927SAndroid Build Coastguard Worker             This->base.device->device_needs_reset = true;
955*61046927SAndroid Build Coastguard Worker         }
956*61046927SAndroid Build Coastguard Worker         if (This->base.device->device_needs_reset) {
957*61046927SAndroid Build Coastguard Worker             DBG("Device is lost. Returning D3DERR_DEVICELOST.\n");
958*61046927SAndroid Build Coastguard Worker             return D3DERR_DEVICELOST;
959*61046927SAndroid Build Coastguard Worker         }
960*61046927SAndroid Build Coastguard Worker     }
961*61046927SAndroid Build Coastguard Worker 
962*61046927SAndroid Build Coastguard Worker     nine_csmt_process(This->base.device);
963*61046927SAndroid Build Coastguard Worker 
964*61046927SAndroid Build Coastguard Worker     hr = present(This, pSourceRect, pDestRect,
965*61046927SAndroid Build Coastguard Worker                  hDestWindowOverride, pDirtyRegion, dwFlags);
966*61046927SAndroid Build Coastguard Worker     if (hr == D3DERR_WASSTILLDRAWING)
967*61046927SAndroid Build Coastguard Worker         return hr;
968*61046927SAndroid Build Coastguard Worker 
969*61046927SAndroid Build Coastguard Worker     if (This->base.device->minor_version_num > 2 &&
970*61046927SAndroid Build Coastguard Worker         This->actx->discard_delayed_release &&
971*61046927SAndroid Build Coastguard Worker         This->params.SwapEffect == D3DSWAPEFFECT_DISCARD &&
972*61046927SAndroid Build Coastguard Worker         This->params.PresentationInterval == D3DPRESENT_INTERVAL_IMMEDIATE) {
973*61046927SAndroid Build Coastguard Worker         int next_buffer = -1;
974*61046927SAndroid Build Coastguard Worker 
975*61046927SAndroid Build Coastguard Worker         while (next_buffer == -1) {
976*61046927SAndroid Build Coastguard Worker             /* Find a free backbuffer */
977*61046927SAndroid Build Coastguard Worker             for (i = 1; i < This->num_back_buffers; i++) {
978*61046927SAndroid Build Coastguard Worker                 if (!p_atomic_read(This->pending_presentation[i]) &&
979*61046927SAndroid Build Coastguard Worker                     ID3DPresent_IsBufferReleased(This->present, This->present_handles[i])) {
980*61046927SAndroid Build Coastguard Worker                     DBG("Found buffer released: %d\n", i);
981*61046927SAndroid Build Coastguard Worker                     next_buffer = i;
982*61046927SAndroid Build Coastguard Worker                     break;
983*61046927SAndroid Build Coastguard Worker                 }
984*61046927SAndroid Build Coastguard Worker             }
985*61046927SAndroid Build Coastguard Worker             if (next_buffer == -1) {
986*61046927SAndroid Build Coastguard Worker                 DBG("Found no buffer released. Waiting for event\n");
987*61046927SAndroid Build Coastguard Worker                 ID3DPresent_WaitBufferReleaseEvent(This->present);
988*61046927SAndroid Build Coastguard Worker             }
989*61046927SAndroid Build Coastguard Worker         }
990*61046927SAndroid Build Coastguard Worker 
991*61046927SAndroid Build Coastguard Worker         /* Free the task (we already checked it is finished) */
992*61046927SAndroid Build Coastguard Worker         if (This->tasks[next_buffer])
993*61046927SAndroid Build Coastguard Worker             _mesa_threadpool_wait_for_task(This->pool, &(This->tasks[next_buffer]));
994*61046927SAndroid Build Coastguard Worker         assert(!*This->pending_presentation[next_buffer] && !This->tasks[next_buffer]);
995*61046927SAndroid Build Coastguard Worker         This->tasks[next_buffer] = This->tasks[0];
996*61046927SAndroid Build Coastguard Worker         This->tasks[0] = NULL;
997*61046927SAndroid Build Coastguard Worker         pending_presentation_temp = This->pending_presentation[next_buffer];
998*61046927SAndroid Build Coastguard Worker         This->pending_presentation[next_buffer] = This->pending_presentation[0];
999*61046927SAndroid Build Coastguard Worker         This->pending_presentation[0] = pending_presentation_temp;
1000*61046927SAndroid Build Coastguard Worker 
1001*61046927SAndroid Build Coastguard Worker         /* Switch with the released buffer */
1002*61046927SAndroid Build Coastguard Worker         pipe_resource_reference(&res, This->buffers[0]->base.resource);
1003*61046927SAndroid Build Coastguard Worker         NineSurface9_SetResourceResize(
1004*61046927SAndroid Build Coastguard Worker             This->buffers[0], This->buffers[next_buffer]->base.resource);
1005*61046927SAndroid Build Coastguard Worker         NineSurface9_SetResourceResize(
1006*61046927SAndroid Build Coastguard Worker             This->buffers[next_buffer], res);
1007*61046927SAndroid Build Coastguard Worker         pipe_resource_reference(&res, NULL);
1008*61046927SAndroid Build Coastguard Worker 
1009*61046927SAndroid Build Coastguard Worker         if (This->present_buffers[0]) {
1010*61046927SAndroid Build Coastguard Worker             pipe_resource_reference(&res, This->present_buffers[0]);
1011*61046927SAndroid Build Coastguard Worker             pipe_resource_reference(&This->present_buffers[0], This->present_buffers[next_buffer]);
1012*61046927SAndroid Build Coastguard Worker             pipe_resource_reference(&This->present_buffers[next_buffer], res);
1013*61046927SAndroid Build Coastguard Worker             pipe_resource_reference(&res, NULL);
1014*61046927SAndroid Build Coastguard Worker         }
1015*61046927SAndroid Build Coastguard Worker 
1016*61046927SAndroid Build Coastguard Worker         handle_temp = This->present_handles[0];
1017*61046927SAndroid Build Coastguard Worker         This->present_handles[0] = This->present_handles[next_buffer];
1018*61046927SAndroid Build Coastguard Worker         This->present_handles[next_buffer] = handle_temp;
1019*61046927SAndroid Build Coastguard Worker     } else {
1020*61046927SAndroid Build Coastguard Worker         switch (This->params.SwapEffect) {
1021*61046927SAndroid Build Coastguard Worker             case D3DSWAPEFFECT_OVERLAY: /* Not implemented, fallback to FLIP */
1022*61046927SAndroid Build Coastguard Worker             case D3DSWAPEFFECT_FLIPEX: /* Allows optimizations over FLIP for windowed mode. */
1023*61046927SAndroid Build Coastguard Worker             case D3DSWAPEFFECT_DISCARD: /* Allows optimizations over FLIP */
1024*61046927SAndroid Build Coastguard Worker             case D3DSWAPEFFECT_FLIP:
1025*61046927SAndroid Build Coastguard Worker                 /* rotate the queue */
1026*61046927SAndroid Build Coastguard Worker                 pipe_resource_reference(&res, This->buffers[0]->base.resource);
1027*61046927SAndroid Build Coastguard Worker                 for (i = 1; i < This->num_back_buffers; i++) {
1028*61046927SAndroid Build Coastguard Worker                     NineSurface9_SetResourceResize(This->buffers[i - 1],
1029*61046927SAndroid Build Coastguard Worker                                                    This->buffers[i]->base.resource);
1030*61046927SAndroid Build Coastguard Worker                 }
1031*61046927SAndroid Build Coastguard Worker                 NineSurface9_SetResourceResize(
1032*61046927SAndroid Build Coastguard Worker                     This->buffers[This->num_back_buffers - 1], res);
1033*61046927SAndroid Build Coastguard Worker                 pipe_resource_reference(&res, NULL);
1034*61046927SAndroid Build Coastguard Worker 
1035*61046927SAndroid Build Coastguard Worker                 if (This->present_buffers[0]) {
1036*61046927SAndroid Build Coastguard Worker                     pipe_resource_reference(&res, This->present_buffers[0]);
1037*61046927SAndroid Build Coastguard Worker                     for (i = 1; i < This->num_back_buffers; i++)
1038*61046927SAndroid Build Coastguard Worker                         pipe_resource_reference(&(This->present_buffers[i-1]), This->present_buffers[i]);
1039*61046927SAndroid Build Coastguard Worker                     pipe_resource_reference(&(This->present_buffers[This->num_back_buffers - 1]), res);
1040*61046927SAndroid Build Coastguard Worker                     pipe_resource_reference(&res, NULL);
1041*61046927SAndroid Build Coastguard Worker                 }
1042*61046927SAndroid Build Coastguard Worker 
1043*61046927SAndroid Build Coastguard Worker                 handle_temp = This->present_handles[0];
1044*61046927SAndroid Build Coastguard Worker                 for (i = 1; i < This->num_back_buffers; i++) {
1045*61046927SAndroid Build Coastguard Worker                     This->present_handles[i-1] = This->present_handles[i];
1046*61046927SAndroid Build Coastguard Worker                 }
1047*61046927SAndroid Build Coastguard Worker                 This->present_handles[This->num_back_buffers - 1] = handle_temp;
1048*61046927SAndroid Build Coastguard Worker                 task_temp = This->tasks[0];
1049*61046927SAndroid Build Coastguard Worker                 for (i = 1; i < This->num_back_buffers; i++) {
1050*61046927SAndroid Build Coastguard Worker                     This->tasks[i-1] = This->tasks[i];
1051*61046927SAndroid Build Coastguard Worker                 }
1052*61046927SAndroid Build Coastguard Worker                 This->tasks[This->num_back_buffers - 1] = task_temp;
1053*61046927SAndroid Build Coastguard Worker                 pending_presentation_temp = This->pending_presentation[0];
1054*61046927SAndroid Build Coastguard Worker                 for (i = 1; i < This->num_back_buffers; i++) {
1055*61046927SAndroid Build Coastguard Worker                     This->pending_presentation[i-1] = This->pending_presentation[i];
1056*61046927SAndroid Build Coastguard Worker                 }
1057*61046927SAndroid Build Coastguard Worker                 This->pending_presentation[This->num_back_buffers - 1] = pending_presentation_temp;
1058*61046927SAndroid Build Coastguard Worker                 break;
1059*61046927SAndroid Build Coastguard Worker 
1060*61046927SAndroid Build Coastguard Worker             case D3DSWAPEFFECT_COPY:
1061*61046927SAndroid Build Coastguard Worker                 /* do nothing */
1062*61046927SAndroid Build Coastguard Worker                 break;
1063*61046927SAndroid Build Coastguard Worker         }
1064*61046927SAndroid Build Coastguard Worker 
1065*61046927SAndroid Build Coastguard Worker         if (This->tasks[0])
1066*61046927SAndroid Build Coastguard Worker             _mesa_threadpool_wait_for_task(This->pool, &(This->tasks[0]));
1067*61046927SAndroid Build Coastguard Worker         assert(!*This->pending_presentation[0]);
1068*61046927SAndroid Build Coastguard Worker 
1069*61046927SAndroid Build Coastguard Worker         ID3DPresent_WaitBufferReleased(This->present, This->present_handles[0]);
1070*61046927SAndroid Build Coastguard Worker     }
1071*61046927SAndroid Build Coastguard Worker 
1072*61046927SAndroid Build Coastguard Worker     This->base.device->context.changed.group |= NINE_STATE_FB;
1073*61046927SAndroid Build Coastguard Worker 
1074*61046927SAndroid Build Coastguard Worker     return hr;
1075*61046927SAndroid Build Coastguard Worker }
1076*61046927SAndroid Build Coastguard Worker 
1077*61046927SAndroid Build Coastguard Worker HRESULT NINE_WINAPI
NineSwapChain9_GetFrontBufferData(struct NineSwapChain9 * This,IDirect3DSurface9 * pDestSurface)1078*61046927SAndroid Build Coastguard Worker NineSwapChain9_GetFrontBufferData( struct NineSwapChain9 *This,
1079*61046927SAndroid Build Coastguard Worker                                    IDirect3DSurface9 *pDestSurface )
1080*61046927SAndroid Build Coastguard Worker {
1081*61046927SAndroid Build Coastguard Worker     struct NineSurface9 *dest_surface = NineSurface9(pDestSurface);
1082*61046927SAndroid Build Coastguard Worker     struct NineDevice9 *pDevice = This->base.device;
1083*61046927SAndroid Build Coastguard Worker     unsigned int width, height;
1084*61046927SAndroid Build Coastguard Worker     struct pipe_resource *temp_resource;
1085*61046927SAndroid Build Coastguard Worker     struct NineSurface9 *temp_surface;
1086*61046927SAndroid Build Coastguard Worker     D3DWindowBuffer *temp_handle;
1087*61046927SAndroid Build Coastguard Worker     D3DSURFACE_DESC desc;
1088*61046927SAndroid Build Coastguard Worker     HRESULT hr;
1089*61046927SAndroid Build Coastguard Worker 
1090*61046927SAndroid Build Coastguard Worker     DBG("GetFrontBufferData: This=%p pDestSurface=%p\n",
1091*61046927SAndroid Build Coastguard Worker         This, pDestSurface);
1092*61046927SAndroid Build Coastguard Worker 
1093*61046927SAndroid Build Coastguard Worker     user_assert(dest_surface->base.pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL);
1094*61046927SAndroid Build Coastguard Worker 
1095*61046927SAndroid Build Coastguard Worker     width = dest_surface->desc.Width;
1096*61046927SAndroid Build Coastguard Worker     height = dest_surface->desc.Height;
1097*61046927SAndroid Build Coastguard Worker 
1098*61046927SAndroid Build Coastguard Worker     /* Note: front window size and destination size are supposed
1099*61046927SAndroid Build Coastguard Worker      * to match. However it's not very clear what should get taken in Windowed
1100*61046927SAndroid Build Coastguard Worker      * mode. It may need a fix */
1101*61046927SAndroid Build Coastguard Worker     create_present_buffer(This, width, height, &temp_resource, &temp_handle);
1102*61046927SAndroid Build Coastguard Worker 
1103*61046927SAndroid Build Coastguard Worker     if (!temp_resource || !temp_handle) {
1104*61046927SAndroid Build Coastguard Worker         return D3DERR_INVALIDCALL;
1105*61046927SAndroid Build Coastguard Worker     }
1106*61046927SAndroid Build Coastguard Worker 
1107*61046927SAndroid Build Coastguard Worker     desc.Type = D3DRTYPE_SURFACE;
1108*61046927SAndroid Build Coastguard Worker     desc.Pool = D3DPOOL_DEFAULT;
1109*61046927SAndroid Build Coastguard Worker     desc.MultiSampleType = D3DMULTISAMPLE_NONE;
1110*61046927SAndroid Build Coastguard Worker     desc.MultiSampleQuality = 0;
1111*61046927SAndroid Build Coastguard Worker     desc.Width = width;
1112*61046927SAndroid Build Coastguard Worker     desc.Height = height;
1113*61046927SAndroid Build Coastguard Worker     /* NineSurface9_CopyDefaultToMem needs same format. */
1114*61046927SAndroid Build Coastguard Worker     desc.Format = dest_surface->desc.Format;
1115*61046927SAndroid Build Coastguard Worker     desc.Usage = D3DUSAGE_RENDERTARGET;
1116*61046927SAndroid Build Coastguard Worker     hr = NineSurface9_new(pDevice, NineUnknown(This), temp_resource, NULL, 0,
1117*61046927SAndroid Build Coastguard Worker                           0, 0, &desc, &temp_surface);
1118*61046927SAndroid Build Coastguard Worker     pipe_resource_reference(&temp_resource, NULL);
1119*61046927SAndroid Build Coastguard Worker     if (FAILED(hr)) {
1120*61046927SAndroid Build Coastguard Worker         DBG("Failed to create temp FrontBuffer surface.\n");
1121*61046927SAndroid Build Coastguard Worker         return hr;
1122*61046927SAndroid Build Coastguard Worker     }
1123*61046927SAndroid Build Coastguard Worker 
1124*61046927SAndroid Build Coastguard Worker     ID3DPresent_FrontBufferCopy(This->present, temp_handle);
1125*61046927SAndroid Build Coastguard Worker 
1126*61046927SAndroid Build Coastguard Worker     NineSurface9_CopyDefaultToMem(dest_surface, temp_surface);
1127*61046927SAndroid Build Coastguard Worker 
1128*61046927SAndroid Build Coastguard Worker     ID3DPresent_DestroyD3DWindowBuffer(This->present, temp_handle);
1129*61046927SAndroid Build Coastguard Worker     NineUnknown_Destroy(NineUnknown(temp_surface));
1130*61046927SAndroid Build Coastguard Worker 
1131*61046927SAndroid Build Coastguard Worker     return D3D_OK;
1132*61046927SAndroid Build Coastguard Worker }
1133*61046927SAndroid Build Coastguard Worker 
1134*61046927SAndroid Build Coastguard Worker HRESULT NINE_WINAPI
NineSwapChain9_GetBackBuffer(struct NineSwapChain9 * This,UINT iBackBuffer,D3DBACKBUFFER_TYPE Type,IDirect3DSurface9 ** ppBackBuffer)1135*61046927SAndroid Build Coastguard Worker NineSwapChain9_GetBackBuffer( struct NineSwapChain9 *This,
1136*61046927SAndroid Build Coastguard Worker                               UINT iBackBuffer,
1137*61046927SAndroid Build Coastguard Worker                               D3DBACKBUFFER_TYPE Type,
1138*61046927SAndroid Build Coastguard Worker                               IDirect3DSurface9 **ppBackBuffer )
1139*61046927SAndroid Build Coastguard Worker {
1140*61046927SAndroid Build Coastguard Worker     DBG("GetBackBuffer: This=%p iBackBuffer=%d Type=%d ppBackBuffer=%p\n",
1141*61046927SAndroid Build Coastguard Worker         This, iBackBuffer, Type, ppBackBuffer);
1142*61046927SAndroid Build Coastguard Worker     (void)user_error(Type == D3DBACKBUFFER_TYPE_MONO);
1143*61046927SAndroid Build Coastguard Worker     /* don't touch ppBackBuffer on error */
1144*61046927SAndroid Build Coastguard Worker     user_assert(ppBackBuffer != NULL, D3DERR_INVALIDCALL);
1145*61046927SAndroid Build Coastguard Worker     user_assert(iBackBuffer < This->params.BackBufferCount, D3DERR_INVALIDCALL);
1146*61046927SAndroid Build Coastguard Worker 
1147*61046927SAndroid Build Coastguard Worker     NineUnknown_AddRef(NineUnknown(This->buffers[iBackBuffer]));
1148*61046927SAndroid Build Coastguard Worker     *ppBackBuffer = (IDirect3DSurface9 *)This->buffers[iBackBuffer];
1149*61046927SAndroid Build Coastguard Worker     return D3D_OK;
1150*61046927SAndroid Build Coastguard Worker }
1151*61046927SAndroid Build Coastguard Worker 
1152*61046927SAndroid Build Coastguard Worker HRESULT NINE_WINAPI
NineSwapChain9_GetRasterStatus(struct NineSwapChain9 * This,D3DRASTER_STATUS * pRasterStatus)1153*61046927SAndroid Build Coastguard Worker NineSwapChain9_GetRasterStatus( struct NineSwapChain9 *This,
1154*61046927SAndroid Build Coastguard Worker                                 D3DRASTER_STATUS *pRasterStatus )
1155*61046927SAndroid Build Coastguard Worker {
1156*61046927SAndroid Build Coastguard Worker     DBG("GetRasterStatus: This=%p pRasterStatus=%p\n",
1157*61046927SAndroid Build Coastguard Worker         This, pRasterStatus);
1158*61046927SAndroid Build Coastguard Worker     user_assert(pRasterStatus != NULL, E_POINTER);
1159*61046927SAndroid Build Coastguard Worker     return ID3DPresent_GetRasterStatus(This->present, pRasterStatus);
1160*61046927SAndroid Build Coastguard Worker }
1161*61046927SAndroid Build Coastguard Worker 
1162*61046927SAndroid Build Coastguard Worker HRESULT NINE_WINAPI
NineSwapChain9_GetDisplayMode(struct NineSwapChain9 * This,D3DDISPLAYMODE * pMode)1163*61046927SAndroid Build Coastguard Worker NineSwapChain9_GetDisplayMode( struct NineSwapChain9 *This,
1164*61046927SAndroid Build Coastguard Worker                                D3DDISPLAYMODE *pMode )
1165*61046927SAndroid Build Coastguard Worker {
1166*61046927SAndroid Build Coastguard Worker     D3DDISPLAYMODEEX mode;
1167*61046927SAndroid Build Coastguard Worker     D3DDISPLAYROTATION rot;
1168*61046927SAndroid Build Coastguard Worker     HRESULT hr;
1169*61046927SAndroid Build Coastguard Worker 
1170*61046927SAndroid Build Coastguard Worker     DBG("GetDisplayMode: This=%p pMode=%p\n",
1171*61046927SAndroid Build Coastguard Worker         This, pMode);
1172*61046927SAndroid Build Coastguard Worker     user_assert(pMode != NULL, E_POINTER);
1173*61046927SAndroid Build Coastguard Worker 
1174*61046927SAndroid Build Coastguard Worker     hr = ID3DPresent_GetDisplayMode(This->present, &mode, &rot);
1175*61046927SAndroid Build Coastguard Worker     if (SUCCEEDED(hr)) {
1176*61046927SAndroid Build Coastguard Worker         pMode->Width = mode.Width;
1177*61046927SAndroid Build Coastguard Worker         pMode->Height = mode.Height;
1178*61046927SAndroid Build Coastguard Worker         pMode->RefreshRate = mode.RefreshRate;
1179*61046927SAndroid Build Coastguard Worker         pMode->Format = mode.Format;
1180*61046927SAndroid Build Coastguard Worker     }
1181*61046927SAndroid Build Coastguard Worker     return hr;
1182*61046927SAndroid Build Coastguard Worker }
1183*61046927SAndroid Build Coastguard Worker 
1184*61046927SAndroid Build Coastguard Worker HRESULT NINE_WINAPI
NineSwapChain9_GetPresentParameters(struct NineSwapChain9 * This,D3DPRESENT_PARAMETERS * pPresentationParameters)1185*61046927SAndroid Build Coastguard Worker NineSwapChain9_GetPresentParameters( struct NineSwapChain9 *This,
1186*61046927SAndroid Build Coastguard Worker                                      D3DPRESENT_PARAMETERS *pPresentationParameters )
1187*61046927SAndroid Build Coastguard Worker {
1188*61046927SAndroid Build Coastguard Worker     DBG("GetPresentParameters: This=%p pPresentationParameters=%p\n",
1189*61046927SAndroid Build Coastguard Worker         This, pPresentationParameters);
1190*61046927SAndroid Build Coastguard Worker     user_assert(pPresentationParameters != NULL, E_POINTER);
1191*61046927SAndroid Build Coastguard Worker     *pPresentationParameters = This->params;
1192*61046927SAndroid Build Coastguard Worker     return D3D_OK;
1193*61046927SAndroid Build Coastguard Worker }
1194*61046927SAndroid Build Coastguard Worker 
1195*61046927SAndroid Build Coastguard Worker IDirect3DSwapChain9Vtbl NineSwapChain9_vtable = {
1196*61046927SAndroid Build Coastguard Worker     (void *)NineUnknown_QueryInterface,
1197*61046927SAndroid Build Coastguard Worker     (void *)NineUnknown_AddRef,
1198*61046927SAndroid Build Coastguard Worker     (void *)NineUnknown_Release,
1199*61046927SAndroid Build Coastguard Worker     (void *)NineSwapChain9_Present,
1200*61046927SAndroid Build Coastguard Worker     (void *)NineSwapChain9_GetFrontBufferData,
1201*61046927SAndroid Build Coastguard Worker     (void *)NineSwapChain9_GetBackBuffer,
1202*61046927SAndroid Build Coastguard Worker     (void *)NineSwapChain9_GetRasterStatus,
1203*61046927SAndroid Build Coastguard Worker     (void *)NineSwapChain9_GetDisplayMode,
1204*61046927SAndroid Build Coastguard Worker     (void *)NineUnknown_GetDevice, /* actually part of SwapChain9 iface */
1205*61046927SAndroid Build Coastguard Worker     (void *)NineSwapChain9_GetPresentParameters
1206*61046927SAndroid Build Coastguard Worker };
1207*61046927SAndroid Build Coastguard Worker 
1208*61046927SAndroid Build Coastguard Worker static const GUID *NineSwapChain9_IIDs[] = {
1209*61046927SAndroid Build Coastguard Worker     &IID_IDirect3DSwapChain9,
1210*61046927SAndroid Build Coastguard Worker     &IID_IUnknown,
1211*61046927SAndroid Build Coastguard Worker     NULL
1212*61046927SAndroid Build Coastguard Worker };
1213*61046927SAndroid Build Coastguard Worker 
1214*61046927SAndroid Build Coastguard Worker HRESULT
NineSwapChain9_new(struct NineDevice9 * pDevice,BOOL implicit,ID3DPresent * pPresent,D3DPRESENT_PARAMETERS * pPresentationParameters,struct d3dadapter9_context * pCTX,HWND hFocusWindow,struct NineSwapChain9 ** ppOut)1215*61046927SAndroid Build Coastguard Worker NineSwapChain9_new( struct NineDevice9 *pDevice,
1216*61046927SAndroid Build Coastguard Worker                     BOOL implicit,
1217*61046927SAndroid Build Coastguard Worker                     ID3DPresent *pPresent,
1218*61046927SAndroid Build Coastguard Worker                     D3DPRESENT_PARAMETERS *pPresentationParameters,
1219*61046927SAndroid Build Coastguard Worker                     struct d3dadapter9_context *pCTX,
1220*61046927SAndroid Build Coastguard Worker                     HWND hFocusWindow,
1221*61046927SAndroid Build Coastguard Worker                     struct NineSwapChain9 **ppOut )
1222*61046927SAndroid Build Coastguard Worker {
1223*61046927SAndroid Build Coastguard Worker     NINE_DEVICE_CHILD_NEW(SwapChain9, ppOut, pDevice, /* args */
1224*61046927SAndroid Build Coastguard Worker                           implicit, pPresent, pPresentationParameters,
1225*61046927SAndroid Build Coastguard Worker                           pCTX, hFocusWindow, NULL);
1226*61046927SAndroid Build Coastguard Worker }
1227*61046927SAndroid Build Coastguard Worker 
1228*61046927SAndroid Build Coastguard Worker BOOL
NineSwapChain9_GetOccluded(struct NineSwapChain9 * This)1229*61046927SAndroid Build Coastguard Worker NineSwapChain9_GetOccluded( struct NineSwapChain9 *This )
1230*61046927SAndroid Build Coastguard Worker {
1231*61046927SAndroid Build Coastguard Worker     if (This->base.device->minor_version_num > 0) {
1232*61046927SAndroid Build Coastguard Worker         return ID3DPresent_GetWindowOccluded(This->present);
1233*61046927SAndroid Build Coastguard Worker     }
1234*61046927SAndroid Build Coastguard Worker 
1235*61046927SAndroid Build Coastguard Worker     return false;
1236*61046927SAndroid Build Coastguard Worker }
1237*61046927SAndroid Build Coastguard Worker 
1238*61046927SAndroid Build Coastguard Worker BOOL
NineSwapChain9_ResolutionMismatch(struct NineSwapChain9 * This)1239*61046927SAndroid Build Coastguard Worker NineSwapChain9_ResolutionMismatch( struct NineSwapChain9 *This )
1240*61046927SAndroid Build Coastguard Worker {
1241*61046927SAndroid Build Coastguard Worker     if (This->base.device->minor_version_num > 1) {
1242*61046927SAndroid Build Coastguard Worker         return ID3DPresent_ResolutionMismatch(This->present);
1243*61046927SAndroid Build Coastguard Worker     }
1244*61046927SAndroid Build Coastguard Worker 
1245*61046927SAndroid Build Coastguard Worker     return false;
1246*61046927SAndroid Build Coastguard Worker }
1247*61046927SAndroid Build Coastguard Worker 
1248*61046927SAndroid Build Coastguard Worker HANDLE
NineSwapChain9_CreateThread(struct NineSwapChain9 * This,void * pFuncAddress,void * pParam)1249*61046927SAndroid Build Coastguard Worker NineSwapChain9_CreateThread( struct NineSwapChain9 *This,
1250*61046927SAndroid Build Coastguard Worker                                  void *pFuncAddress,
1251*61046927SAndroid Build Coastguard Worker                                  void *pParam )
1252*61046927SAndroid Build Coastguard Worker {
1253*61046927SAndroid Build Coastguard Worker     if (This->base.device->minor_version_num > 1) {
1254*61046927SAndroid Build Coastguard Worker         return ID3DPresent_CreateThread(This->present, pFuncAddress, pParam);
1255*61046927SAndroid Build Coastguard Worker     }
1256*61046927SAndroid Build Coastguard Worker 
1257*61046927SAndroid Build Coastguard Worker     return NULL;
1258*61046927SAndroid Build Coastguard Worker }
1259*61046927SAndroid Build Coastguard Worker 
1260*61046927SAndroid Build Coastguard Worker void
NineSwapChain9_WaitForThread(struct NineSwapChain9 * This,HANDLE thread)1261*61046927SAndroid Build Coastguard Worker NineSwapChain9_WaitForThread( struct NineSwapChain9 *This,
1262*61046927SAndroid Build Coastguard Worker                                   HANDLE thread )
1263*61046927SAndroid Build Coastguard Worker {
1264*61046927SAndroid Build Coastguard Worker     if (This->base.device->minor_version_num > 1) {
1265*61046927SAndroid Build Coastguard Worker         (void) ID3DPresent_WaitForThread(This->present, thread);
1266*61046927SAndroid Build Coastguard Worker     }
1267*61046927SAndroid Build Coastguard Worker }
1268*61046927SAndroid Build Coastguard Worker 
1269*61046927SAndroid Build Coastguard Worker static int
NineSwapChain9_GetBackBufferCountForParams(struct NineSwapChain9 * This,D3DPRESENT_PARAMETERS * pParams)1270*61046927SAndroid Build Coastguard Worker NineSwapChain9_GetBackBufferCountForParams( struct NineSwapChain9 *This,
1271*61046927SAndroid Build Coastguard Worker                                             D3DPRESENT_PARAMETERS *pParams )
1272*61046927SAndroid Build Coastguard Worker {
1273*61046927SAndroid Build Coastguard Worker     int count = pParams->BackBufferCount;
1274*61046927SAndroid Build Coastguard Worker 
1275*61046927SAndroid Build Coastguard Worker     /* When we have flip behaviour, d3d9 expects we get back the screen buffer when we flip.
1276*61046927SAndroid Build Coastguard Worker      * Here we don't get back the initial content of the screen. To emulate the behaviour
1277*61046927SAndroid Build Coastguard Worker      * we allocate an additional buffer */
1278*61046927SAndroid Build Coastguard Worker     if (pParams->SwapEffect != D3DSWAPEFFECT_COPY)
1279*61046927SAndroid Build Coastguard Worker         count++;
1280*61046927SAndroid Build Coastguard Worker     /* With DISCARD, as there is no guarantee about the buffer contents, we can use
1281*61046927SAndroid Build Coastguard Worker      * an arbitrary number of buffers */
1282*61046927SAndroid Build Coastguard Worker     if (pParams->SwapEffect == D3DSWAPEFFECT_DISCARD) {
1283*61046927SAndroid Build Coastguard Worker         /* thread_submit's can have maximum count or This->actx->throttling_value + 1
1284*61046927SAndroid Build Coastguard Worker          * frames in flight being rendered and not shown.
1285*61046927SAndroid Build Coastguard Worker          * Do not let count decrease that number */
1286*61046927SAndroid Build Coastguard Worker         if (This->actx->thread_submit && count < This->desired_fences)
1287*61046927SAndroid Build Coastguard Worker             count = This->desired_fences;
1288*61046927SAndroid Build Coastguard Worker         /* When we enable AllowDISCARDDelayedRelease, we must ensure
1289*61046927SAndroid Build Coastguard Worker          * to have at least 4 buffers to meet INTERVAL_IMMEDIATE,
1290*61046927SAndroid Build Coastguard Worker          * since the display server/compositor can hold 3 buffers
1291*61046927SAndroid Build Coastguard Worker          * without releasing them:
1292*61046927SAndroid Build Coastguard Worker          * . Buffer on screen.
1293*61046927SAndroid Build Coastguard Worker          * . Buffer scheduled kernel side to be next on screen.
1294*61046927SAndroid Build Coastguard Worker          * . Last buffer sent. */
1295*61046927SAndroid Build Coastguard Worker         if (This->base.device->minor_version_num > 2 &&
1296*61046927SAndroid Build Coastguard Worker             This->actx->discard_delayed_release &&
1297*61046927SAndroid Build Coastguard Worker             pParams->PresentationInterval == D3DPRESENT_INTERVAL_IMMEDIATE) {
1298*61046927SAndroid Build Coastguard Worker             if (This->actx->thread_submit && count < 4)
1299*61046927SAndroid Build Coastguard Worker                 count = 4;
1300*61046927SAndroid Build Coastguard Worker             /* When thread_submit is not used, 5 buffers are actually needed,
1301*61046927SAndroid Build Coastguard Worker              * because in case a pageflip is missed because rendering wasn't finished,
1302*61046927SAndroid Build Coastguard Worker              * the Xserver will hold 4 buffers. */
1303*61046927SAndroid Build Coastguard Worker             else if (!This->actx->thread_submit && count < 5)
1304*61046927SAndroid Build Coastguard Worker                 count = 5;
1305*61046927SAndroid Build Coastguard Worker             /* Somehow this cases needs 5 with thread_submit, or else you get a small performance hit */
1306*61046927SAndroid Build Coastguard Worker             if (This->actx->tearfree_discard && count < 5)
1307*61046927SAndroid Build Coastguard Worker                 count = 5;
1308*61046927SAndroid Build Coastguard Worker         }
1309*61046927SAndroid Build Coastguard Worker     }
1310*61046927SAndroid Build Coastguard Worker 
1311*61046927SAndroid Build Coastguard Worker     return count;
1312*61046927SAndroid Build Coastguard Worker }
1313