2 * Copyright 2011 Joakim Sindholt <opensource@zhasha.com>
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE. */
23 #include "swapchain9.h"
27 #include "nine_helpers.h"
28 #include "nine_pipe.h"
29 #include "nine_dump.h"
31 #include "util/u_inlines.h"
32 #include "util/u_surface.h"
33 #include "hud/hud_context.h"
34 #include "state_tracker/drm_driver.h"
36 #define DBG_CHANNEL DBG_SWAPCHAIN
38 #define UNTESTED(n) DBG("UNTESTED point %d. Please tell if it worked\n", n)
41 NineSwapChain9_ctor( struct NineSwapChain9
*This
,
42 struct NineUnknownParams
*pParams
,
44 ID3DPresent
*pPresent
,
45 D3DPRESENT_PARAMETERS
*pPresentationParameters
,
46 struct d3dadapter9_context
*pCTX
,
48 D3DDISPLAYMODEEX
*mode
)
52 DBG("This=%p pDevice=%p pPresent=%p pCTX=%p hFocusWindow=%p\n",
53 This
, pParams
->device
, pPresent
, pCTX
, hFocusWindow
);
55 hr
= NineUnknown_ctor(&This
->base
, pParams
);
59 This
->screen
= NineDevice9_GetScreen(This
->base
.device
);
60 This
->pipe
= NineDevice9_GetPipe(This
->base
.device
);
61 This
->cso
= NineDevice9_GetCSO(This
->base
.device
);
62 This
->implicit
= implicit
;
64 This
->present
= pPresent
;
67 ID3DPresent_AddRef(pPresent
);
69 if (!pPresentationParameters
->hDeviceWindow
)
70 pPresentationParameters
->hDeviceWindow
= hFocusWindow
;
72 This
->rendering_done
= FALSE
;
73 return NineSwapChain9_Resize(This
, pPresentationParameters
, mode
);
76 static D3DWindowBuffer
*
77 D3DWindowBuffer_create(struct NineSwapChain9
*This
,
78 struct pipe_resource
*resource
,
82 struct winsys_handle whandle
;
85 memset(&whandle
, 0, sizeof(whandle
));
86 whandle
.type
= DRM_API_HANDLE_TYPE_FD
;
87 This
->screen
->resource_get_handle(This
->screen
, resource
, &whandle
);
88 stride
= whandle
.stride
;
89 dmaBufFd
= whandle
.handle
;
90 ID3DPresent_NewD3DWindowBufferFromDmaBuf(This
->present
,
102 NineSwapChain9_Resize( struct NineSwapChain9
*This
,
103 D3DPRESENT_PARAMETERS
*pParams
,
104 D3DDISPLAYMODEEX
*mode
)
106 struct NineDevice9
*pDevice
= This
->base
.device
;
107 struct NineSurface9
**bufs
;
108 D3DSURFACE_DESC desc
;
110 struct pipe_resource
*resource
, tmplt
;
112 BOOL has_present_buffers
= FALSE
;
114 unsigned i
, oldBufferCount
, newBufferCount
;
116 DBG("This=%p pParams=%p\n", This
, pParams
);
117 user_assert(pParams
!= NULL
, E_POINTER
);
120 "BackBufferWidth: %u\n"
121 "BackBufferHeight: %u\n"
122 "BackBufferFormat: %s\n"
123 "BackBufferCount: %u\n"
124 "MultiSampleType: %u\n"
125 "MultiSampleQuality: %u\n"
127 "hDeviceWindow: %p\n"
129 "EnableAutoDepthStencil: %i\n"
130 "AutoDepthStencilFormat: %s\n"
132 "FullScreen_RefreshRateInHz: %u\n"
133 "PresentationInterval: %x\n", pParams
,
134 pParams
->BackBufferWidth
, pParams
->BackBufferHeight
,
135 d3dformat_to_string(pParams
->BackBufferFormat
),
136 pParams
->BackBufferCount
,
137 pParams
->MultiSampleType
, pParams
->MultiSampleQuality
,
138 pParams
->SwapEffect
, pParams
->hDeviceWindow
, pParams
->Windowed
,
139 pParams
->EnableAutoDepthStencil
,
140 d3dformat_to_string(pParams
->AutoDepthStencilFormat
),
141 nine_D3DPRESENTFLAG_to_str(pParams
->Flags
),
142 pParams
->FullScreen_RefreshRateInHz
,
143 pParams
->PresentationInterval
);
145 if (pParams
->SwapEffect
== D3DSWAPEFFECT_COPY
&&
146 pParams
->BackBufferCount
> 1) {
147 pParams
->BackBufferCount
= 1;
150 if (pParams
->BackBufferCount
> 3) {
151 pParams
->BackBufferCount
= 3;
154 if (pParams
->BackBufferCount
== 0) {
155 pParams
->BackBufferCount
= 1;
158 if (pParams
->BackBufferFormat
== D3DFMT_UNKNOWN
) {
159 pParams
->BackBufferFormat
= D3DFMT_A8R8G8B8
;
162 This
->desired_fences
= This
->actx
->throttling
? This
->actx
->throttling_value
+ 1 : 0;
163 /* +1 because we add the fence of the current buffer before popping an old one */
164 if (This
->desired_fences
> DRI_SWAP_FENCES_MAX
)
165 This
->desired_fences
= DRI_SWAP_FENCES_MAX
;
167 if (mode
&& This
->mode
) {
168 *(This
->mode
) = *mode
;
170 This
->mode
= malloc(sizeof(D3DDISPLAYMODEEX
));
171 memcpy(This
->mode
, mode
, sizeof(D3DDISPLAYMODEEX
));
172 } else if (This
->mode
) {
177 /* Note: It is the role of the backend to fill if neccessary
178 * BackBufferWidth and BackBufferHeight */
179 ID3DPresent_SetPresentParameters(This
->present
, pParams
, This
->mode
);
181 /* When we have flip behaviour, d3d9 expects we get back the screen buffer when we flip.
182 * Here we don't get back the initial content of the screen. To emulate the behaviour
183 * we allocate an additional buffer */
184 oldBufferCount
= This
->params
.BackBufferCount
?
185 (This
->params
.BackBufferCount
+
186 (This
->params
.SwapEffect
!= D3DSWAPEFFECT_COPY
)) : 0;
187 newBufferCount
= pParams
->BackBufferCount
+
188 (pParams
->SwapEffect
!= D3DSWAPEFFECT_COPY
);
190 pf
= d3d9_to_pipe_format(pParams
->BackBufferFormat
);
191 if (This
->actx
->linear_framebuffer
||
192 (pf
!= PIPE_FORMAT_B8G8R8X8_UNORM
&&
193 pf
!= PIPE_FORMAT_B8G8R8A8_UNORM
) ||
194 pParams
->SwapEffect
!= D3DSWAPEFFECT_DISCARD
||
195 pParams
->MultiSampleType
>= 2 ||
196 (This
->actx
->ref
&& This
->actx
->ref
== This
->screen
))
197 has_present_buffers
= TRUE
;
199 /* Note: the buffer depth has to match the window depth.
200 * In practice, ARGB buffers can be used with windows
201 * of depth 24. Windows of depth 32 are extremely rare.
202 * So even if the buffer is ARGB, say it is depth 24.
203 * It is common practice, for example that's how
204 * glamor implements depth 24.
205 * TODO: handle windows with other depths. Not possible in the short term.
206 * For example 16 bits.*/
209 tmplt
.target
= PIPE_TEXTURE_2D
;
210 tmplt
.width0
= pParams
->BackBufferWidth
;
211 tmplt
.height0
= pParams
->BackBufferHeight
;
213 tmplt
.last_level
= 0;
214 tmplt
.array_size
= 1;
215 tmplt
.usage
= PIPE_USAGE_DEFAULT
;
218 desc
.Type
= D3DRTYPE_SURFACE
;
219 desc
.Pool
= D3DPOOL_DEFAULT
;
220 desc
.MultiSampleType
= pParams
->MultiSampleType
;
221 desc
.MultiSampleQuality
= 0;
222 desc
.Width
= pParams
->BackBufferWidth
;
223 desc
.Height
= pParams
->BackBufferHeight
;
225 for (i
= 0; i
< oldBufferCount
; i
++) {
226 ID3DPresent_DestroyD3DWindowBuffer(This
->present
, This
->present_handles
[i
]);
227 This
->present_handles
[i
] = NULL
;
228 if (This
->present_buffers
)
229 pipe_resource_reference(&(This
->present_buffers
[i
]), NULL
);
232 if (!has_present_buffers
&& This
->present_buffers
) {
233 FREE(This
->present_buffers
);
234 This
->present_buffers
= NULL
;
237 if (newBufferCount
!= oldBufferCount
) {
238 for (i
= newBufferCount
; i
< oldBufferCount
;
240 NineUnknown_Detach(NineUnknown(This
->buffers
[i
]));
242 bufs
= REALLOC(This
->buffers
,
243 oldBufferCount
* sizeof(This
->buffers
[0]),
244 newBufferCount
* sizeof(This
->buffers
[0]));
246 return E_OUTOFMEMORY
;
247 This
->buffers
= bufs
;
248 if (has_present_buffers
) {
249 This
->present_buffers
= REALLOC(This
->present_buffers
,
250 This
->present_buffers
== NULL
? 0 : oldBufferCount
* sizeof(struct pipe_resource
*),
251 newBufferCount
* sizeof(struct pipe_resource
*));
252 memset(This
->present_buffers
, 0, newBufferCount
* sizeof(struct pipe_resource
*));
254 This
->present_handles
= REALLOC(This
->present_handles
,
255 oldBufferCount
* sizeof(D3DWindowBuffer
*),
256 newBufferCount
* sizeof(D3DWindowBuffer
*));
257 for (i
= oldBufferCount
; i
< newBufferCount
; ++i
) {
258 This
->buffers
[i
] = NULL
;
259 This
->present_handles
[i
] = NULL
;
263 for (i
= 0; i
< newBufferCount
; ++i
) {
264 tmplt
.format
= d3d9_to_pipe_format(pParams
->BackBufferFormat
);
265 tmplt
.bind
= PIPE_BIND_SAMPLER_VIEW
| PIPE_BIND_TRANSFER_READ
|
266 PIPE_BIND_TRANSFER_WRITE
| PIPE_BIND_RENDER_TARGET
;
267 tmplt
.nr_samples
= pParams
->MultiSampleType
;
268 if (!has_present_buffers
)
269 tmplt
.bind
|= PIPE_BIND_SHARED
| PIPE_BIND_SCANOUT
| PIPE_BIND_DISPLAY_TARGET
;
270 resource
= This
->screen
->resource_create(This
->screen
, &tmplt
);
272 DBG("Failed to create pipe_resource.\n");
273 return D3DERR_OUTOFVIDEOMEMORY
;
275 if (pParams
->Flags
& D3DPRESENTFLAG_LOCKABLE_BACKBUFFER
)
276 resource
->flags
|= NINE_RESOURCE_FLAG_LOCKABLE
;
277 if (This
->buffers
[i
]) {
278 NineSurface9_SetResourceResize(This
->buffers
[i
], resource
);
279 if (has_present_buffers
)
280 pipe_resource_reference(&resource
, NULL
);
282 desc
.Format
= pParams
->BackBufferFormat
;
283 desc
.Usage
= D3DUSAGE_RENDERTARGET
;
284 hr
= NineSurface9_new(pDevice
, NineUnknown(This
), resource
, 0,
285 0, 0, &desc
, &This
->buffers
[i
]);
286 if (has_present_buffers
)
287 pipe_resource_reference(&resource
, NULL
);
289 DBG("Failed to create RT surface.\n");
292 This
->buffers
[i
]->base
.base
.forward
= FALSE
;
294 if (has_present_buffers
) {
295 tmplt
.format
= PIPE_FORMAT_B8G8R8X8_UNORM
;
296 tmplt
.bind
= PIPE_BIND_SAMPLER_VIEW
| PIPE_BIND_SHARED
| PIPE_BIND_SCANOUT
| PIPE_BIND_DISPLAY_TARGET
;
297 tmplt
.nr_samples
= 0;
298 if (This
->actx
->linear_framebuffer
)
299 tmplt
.bind
|= PIPE_BIND_LINEAR
;
300 if (pParams
->SwapEffect
!= D3DSWAPEFFECT_DISCARD
)
301 tmplt
.bind
|= PIPE_BIND_RENDER_TARGET
;
302 resource
= This
->screen
->resource_create(This
->screen
, &tmplt
);
303 pipe_resource_reference(&(This
->present_buffers
[i
]), resource
);
305 This
->present_handles
[i
] = D3DWindowBuffer_create(This
, resource
, depth
);
306 if (!has_present_buffers
)
307 pipe_resource_reference(&resource
, NULL
);
309 if (pParams
->EnableAutoDepthStencil
) {
310 tmplt
.format
= d3d9_to_pipe_format(pParams
->AutoDepthStencilFormat
);
311 tmplt
.bind
= PIPE_BIND_SAMPLER_VIEW
| PIPE_BIND_TRANSFER_READ
|
312 PIPE_BIND_TRANSFER_WRITE
| PIPE_BIND_DEPTH_STENCIL
;
313 tmplt
.nr_samples
= pParams
->MultiSampleType
;
315 resource
= This
->screen
->resource_create(This
->screen
, &tmplt
);
317 DBG("Failed to create pipe_resource for depth buffer.\n");
318 return D3DERR_OUTOFVIDEOMEMORY
;
321 NineSurface9_SetResourceResize(This
->zsbuf
, resource
);
322 pipe_resource_reference(&resource
, NULL
);
324 /* XXX wine thinks the container of this should be the device */
325 desc
.Format
= pParams
->AutoDepthStencilFormat
;
326 desc
.Usage
= D3DUSAGE_DEPTHSTENCIL
;
327 hr
= NineSurface9_new(pDevice
, NineUnknown(pDevice
), resource
, 0,
328 0, 0, &desc
, &This
->zsbuf
);
329 pipe_resource_reference(&resource
, NULL
);
331 DBG("Failed to create ZS surface.\n");
334 This
->zsbuf
->base
.base
.forward
= FALSE
;
338 This
->params
= *pParams
;
343 /* Throttling: code adapted from the dri state tracker */
346 * swap_fences_pop_front - pull a fence from the throttle queue
348 * If the throttle queue is filled to the desired number of fences,
349 * pull fences off the queue until the number is less than the desired
350 * number of fences, and return the last fence pulled.
352 static struct pipe_fence_handle
*
353 swap_fences_pop_front(struct NineSwapChain9
*This
)
355 struct pipe_screen
*screen
= This
->screen
;
356 struct pipe_fence_handle
*fence
= NULL
;
358 if (This
->desired_fences
== 0)
361 if (This
->cur_fences
>= This
->desired_fences
) {
362 screen
->fence_reference(screen
, &fence
, This
->swap_fences
[This
->tail
]);
363 screen
->fence_reference(screen
, &This
->swap_fences
[This
->tail
++], NULL
);
364 This
->tail
&= DRI_SWAP_FENCES_MASK
;
372 * swap_fences_see_front - same than swap_fences_pop_front without
377 static struct pipe_fence_handle
*
378 swap_fences_see_front(struct NineSwapChain9
*This
)
380 struct pipe_screen
*screen
= This
->screen
;
381 struct pipe_fence_handle
*fence
= NULL
;
383 if (This
->desired_fences
== 0)
386 if (This
->cur_fences
>= This
->desired_fences
) {
387 screen
->fence_reference(screen
, &fence
, This
->swap_fences
[This
->tail
]);
394 * swap_fences_push_back - push a fence onto the throttle queue at the back
396 * push a fence onto the throttle queue and pull fences of the queue
397 * so that the desired number of fences are on the queue.
400 swap_fences_push_back(struct NineSwapChain9
*This
,
401 struct pipe_fence_handle
*fence
)
403 struct pipe_screen
*screen
= This
->screen
;
405 if (!fence
|| This
->desired_fences
== 0)
408 while(This
->cur_fences
== This
->desired_fences
)
409 swap_fences_pop_front(This
);
412 screen
->fence_reference(screen
, &This
->swap_fences
[This
->head
++],
414 This
->head
&= DRI_SWAP_FENCES_MASK
;
419 * swap_fences_unref - empty the throttle queue
421 * pulls fences of the throttle queue until it is empty.
424 swap_fences_unref(struct NineSwapChain9
*This
)
426 struct pipe_screen
*screen
= This
->screen
;
428 while(This
->cur_fences
) {
429 screen
->fence_reference(screen
, &This
->swap_fences
[This
->tail
++], NULL
);
430 This
->tail
&= DRI_SWAP_FENCES_MASK
;
436 NineSwapChain9_dtor( struct NineSwapChain9
*This
)
440 DBG("This=%p\n", This
);
443 for (i
= 0; i
< This
->params
.BackBufferCount
; i
++) {
444 NineUnknown_Destroy(NineUnknown(This
->buffers
[i
]));
445 ID3DPresent_DestroyD3DWindowBuffer(This
->present
, This
->present_handles
[i
]);
446 if (This
->present_buffers
)
447 pipe_resource_reference(&(This
->present_buffers
[i
]), NULL
);
450 FREE(This
->present_buffers
);
453 NineUnknown_Destroy(NineUnknown(This
->zsbuf
));
456 ID3DPresent_Release(This
->present
);
458 swap_fences_unref(This
);
459 NineUnknown_dtor(&This
->base
);
463 create_present_buffer( struct NineSwapChain9
*This
,
464 unsigned int width
, unsigned int height
,
465 struct pipe_resource
**resource
,
466 D3DWindowBuffer
**present_handle
)
468 struct pipe_resource tmplt
;
470 tmplt
.target
= PIPE_TEXTURE_2D
;
471 tmplt
.width0
= width
;
472 tmplt
.height0
= height
;
474 tmplt
.last_level
= 0;
475 tmplt
.array_size
= 1;
476 tmplt
.usage
= PIPE_USAGE_DEFAULT
;
478 tmplt
.format
= PIPE_FORMAT_B8G8R8X8_UNORM
;
479 tmplt
.bind
= PIPE_BIND_SAMPLER_VIEW
| PIPE_BIND_TRANSFER_READ
|
480 PIPE_BIND_TRANSFER_WRITE
| PIPE_BIND_RENDER_TARGET
|
481 PIPE_BIND_SHARED
| PIPE_BIND_SCANOUT
| PIPE_BIND_DISPLAY_TARGET
;
482 tmplt
.nr_samples
= 0;
483 if (This
->actx
->linear_framebuffer
)
484 tmplt
.bind
|= PIPE_BIND_LINEAR
;
485 *resource
= This
->screen
->resource_create(This
->screen
, &tmplt
);
487 *present_handle
= D3DWindowBuffer_create(This
, *resource
, 24);
491 handle_draw_cursor_and_hud( struct NineSwapChain9
*This
, struct pipe_resource
*resource
)
493 struct NineDevice9
*device
= This
->base
.device
;
494 struct pipe_blit_info blit
;
496 if (device
->cursor
.software
&& device
->cursor
.visible
&& device
->cursor
.w
) {
497 blit
.src
.resource
= device
->cursor
.image
;
499 blit
.src
.format
= device
->cursor
.image
->format
;
503 blit
.src
.box
.depth
= 1;
504 blit
.src
.box
.width
= device
->cursor
.w
;
505 blit
.src
.box
.height
= device
->cursor
.h
;
507 blit
.dst
.resource
= resource
;
509 blit
.dst
.format
= resource
->format
;
511 blit
.dst
.box
.depth
= 1;
513 blit
.mask
= PIPE_MASK_RGBA
;
514 blit
.filter
= PIPE_TEX_FILTER_NEAREST
;
515 blit
.scissor_enable
= FALSE
;
517 ID3DPresent_GetCursorPos(This
->present
, &device
->cursor
.pos
);
519 /* NOTE: blit messes up when box.x + box.width < 0, fix driver */
520 blit
.dst
.box
.x
= MAX2(device
->cursor
.pos
.x
, 0) - device
->cursor
.hotspot
.x
;
521 blit
.dst
.box
.y
= MAX2(device
->cursor
.pos
.y
, 0) - device
->cursor
.hotspot
.y
;
522 blit
.dst
.box
.width
= blit
.src
.box
.width
;
523 blit
.dst
.box
.height
= blit
.src
.box
.height
;
525 DBG("Blitting cursor(%ux%u) to (%i,%i).\n",
526 blit
.src
.box
.width
, blit
.src
.box
.height
,
527 blit
.dst
.box
.x
, blit
.dst
.box
.y
);
529 This
->pipe
->blit(This
->pipe
, &blit
);
532 if (device
->hud
&& resource
) {
533 hud_draw(device
->hud
, resource
); /* XXX: no offset */
534 /* HUD doesn't clobber stipple */
535 NineDevice9_RestoreNonCSOState(device
, ~0x2);
539 static INLINE HRESULT
540 present( struct NineSwapChain9
*This
,
541 const RECT
*pSourceRect
,
542 const RECT
*pDestRect
,
543 HWND hDestWindowOverride
,
544 const RGNDATA
*pDirtyRegion
,
547 struct pipe_resource
*resource
;
548 struct pipe_fence_handle
*fence
;
550 struct pipe_blit_info blit
;
552 DBG("present: This=%p pSourceRect=%p pDestRect=%p "
553 "pDirtyRegion=%p hDestWindowOverride=%p"
554 "dwFlags=%d resource=%p\n",
555 This
, pSourceRect
, pDestRect
, pDirtyRegion
,
556 hDestWindowOverride
, (int)dwFlags
, This
->buffers
[0]->base
.resource
);
559 DBG("pSourceRect = (%u..%u)x(%u..%u)\n",
560 pSourceRect
->left
, pSourceRect
->right
,
561 pSourceRect
->top
, pSourceRect
->bottom
);
563 DBG("pDestRect = (%u..%u)x(%u..%u)\n",
564 pDestRect
->left
, pDestRect
->right
,
565 pDestRect
->top
, pDestRect
->bottom
);
567 /* TODO: in the case the source and destination rect have different size:
568 * We need to allocate a new buffer, and do a blit to it to resize.
569 * We can't use the present_buffer for that since when we created it,
570 * we couldn't guess which size would have been needed.
571 * If pDestRect or pSourceRect is null, we have to check the sizes
572 * from the source size, and the destination window size.
573 * In this case, either resize rngdata, or pass NULL instead
575 /* Note: This->buffers[0]->level should always be 0 */
577 if (This
->rendering_done
)
578 goto bypass_rendering
;
580 resource
= This
->buffers
[0]->base
.resource
;
582 if (This
->params
.SwapEffect
== D3DSWAPEFFECT_DISCARD
)
583 handle_draw_cursor_and_hud(This
, resource
);
585 if (This
->present_buffers
) {
586 blit
.src
.resource
= resource
;
588 blit
.src
.format
= resource
->format
;
590 blit
.src
.box
.depth
= 1;
593 blit
.src
.box
.width
= resource
->width0
;
594 blit
.src
.box
.height
= resource
->height0
;
596 resource
= This
->present_buffers
[0];
598 blit
.dst
.resource
= resource
;
600 blit
.dst
.format
= resource
->format
;
602 blit
.dst
.box
.depth
= 1;
605 blit
.dst
.box
.width
= resource
->width0
;
606 blit
.dst
.box
.height
= resource
->height0
;
608 blit
.mask
= PIPE_MASK_RGBA
;
609 blit
.filter
= PIPE_TEX_FILTER_NEAREST
;
610 blit
.scissor_enable
= FALSE
;
612 This
->pipe
->blit(This
->pipe
, &blit
);
615 if (This
->params
.SwapEffect
!= D3DSWAPEFFECT_DISCARD
)
616 handle_draw_cursor_and_hud(This
, resource
);
619 This
->pipe
->flush(This
->pipe
, &fence
, PIPE_FLUSH_END_OF_FRAME
);
621 swap_fences_push_back(This
, fence
);
622 This
->screen
->fence_reference(This
->screen
, &fence
, NULL
);
625 This
->rendering_done
= TRUE
;
628 if (dwFlags
& D3DPRESENT_DONOTWAIT
) {
630 BOOL still_draw
= FALSE
;
631 fence
= swap_fences_see_front(This
);
633 still_draw
= !This
->screen
->fence_signalled(This
->screen
, fence
);
634 This
->screen
->fence_reference(This
->screen
, &fence
, NULL
);
637 return D3DERR_WASSTILLDRAWING
;
640 fence
= swap_fences_pop_front(This
);
642 (void) This
->screen
->fence_finish(This
->screen
, fence
, PIPE_TIMEOUT_INFINITE
);
643 This
->screen
->fence_reference(This
->screen
, &fence
, NULL
);
646 if (This
->present_buffers
)
647 resource
= This
->present_buffers
[0];
649 resource
= This
->buffers
[0]->base
.resource
;
650 This
->pipe
->flush_resource(This
->pipe
, resource
);
651 hr
= ID3DPresent_PresentBuffer(This
->present
, This
->present_handles
[0], hDestWindowOverride
, pSourceRect
, pDestRect
, pDirtyRegion
, dwFlags
);
653 if (FAILED(hr
)) { UNTESTED(3);return hr
; }
655 This
->rendering_done
= FALSE
;
661 NineSwapChain9_Present( struct NineSwapChain9
*This
,
662 const RECT
*pSourceRect
,
663 const RECT
*pDestRect
,
664 HWND hDestWindowOverride
,
665 const RGNDATA
*pDirtyRegion
,
668 struct pipe_resource
*res
= NULL
;
669 D3DWindowBuffer
*handle_temp
;
672 HRESULT hr
= present(This
, pSourceRect
, pDestRect
,
673 hDestWindowOverride
, pDirtyRegion
, dwFlags
);
675 if (hr
== D3DERR_WASSTILLDRAWING
)
678 switch (This
->params
.SwapEffect
) {
679 case D3DSWAPEFFECT_FLIP
:
681 case D3DSWAPEFFECT_DISCARD
:
682 /* rotate the queue */;
683 pipe_resource_reference(&res
, This
->buffers
[0]->base
.resource
);
684 for (i
= 1; i
<= This
->params
.BackBufferCount
; i
++) {
685 NineSurface9_SetResourceResize(This
->buffers
[i
- 1],
686 This
->buffers
[i
]->base
.resource
);
688 NineSurface9_SetResourceResize(
689 This
->buffers
[This
->params
.BackBufferCount
], res
);
690 pipe_resource_reference(&res
, NULL
);
692 if (This
->present_buffers
) {
693 pipe_resource_reference(&res
, This
->present_buffers
[0]);
694 for (i
= 1; i
<= This
->params
.BackBufferCount
; i
++)
695 pipe_resource_reference(&(This
->present_buffers
[i
-1]), This
->present_buffers
[i
]);
696 pipe_resource_reference(&(This
->present_buffers
[This
->params
.BackBufferCount
]), res
);
697 pipe_resource_reference(&res
, NULL
);
700 handle_temp
= This
->present_handles
[0];
701 for (i
= 1; i
<= This
->params
.BackBufferCount
; i
++) {
702 This
->present_handles
[i
-1] = This
->present_handles
[i
];
704 This
->present_handles
[This
->params
.BackBufferCount
] = handle_temp
;
707 case D3DSWAPEFFECT_COPY
:
712 case D3DSWAPEFFECT_OVERLAY
:
713 /* XXX not implemented */
716 case D3DSWAPEFFECT_FLIPEX
:
717 /* XXX not implemented */
721 ID3DPresent_WaitBufferReleased(This
->present
, This
->present_handles
[0]);
723 This
->base
.device
->state
.changed
.group
|= NINE_STATE_FB
;
724 nine_update_state(This
->base
.device
, NINE_STATE_FB
);
730 NineSwapChain9_GetFrontBufferData( struct NineSwapChain9
*This
,
731 IDirect3DSurface9
*pDestSurface
)
733 struct NineSurface9
*dest_surface
= NineSurface9(pDestSurface
);
734 struct NineDevice9
*pDevice
= This
->base
.device
;
735 unsigned int width
, height
;
736 struct pipe_resource
*temp_resource
;
737 struct NineSurface9
*temp_surface
;
738 D3DWindowBuffer
*temp_handle
;
739 D3DSURFACE_DESC desc
;
742 DBG("GetFrontBufferData: This=%p pDestSurface=%p\n",
745 width
= dest_surface
->desc
.Width
;
746 height
= dest_surface
->desc
.Height
;
748 /* Note: front window size and destination size are supposed
749 * to match. However it's not very clear what should get taken in Windowed
750 * mode. It may need a fix */
751 create_present_buffer(This
, width
, height
, &temp_resource
, &temp_handle
);
753 desc
.Type
= D3DRTYPE_SURFACE
;
754 desc
.Pool
= D3DPOOL_DEFAULT
;
755 desc
.MultiSampleType
= D3DMULTISAMPLE_NONE
;
756 desc
.MultiSampleQuality
= 0;
758 desc
.Height
= height
;
759 /* NineSurface9_CopySurface needs same format. */
760 desc
.Format
= dest_surface
->desc
.Format
;
761 desc
.Usage
= D3DUSAGE_RENDERTARGET
;
762 hr
= NineSurface9_new(pDevice
, NineUnknown(This
), temp_resource
, 0,
763 0, 0, &desc
, &temp_surface
);
764 pipe_resource_reference(&temp_resource
, NULL
);
766 DBG("Failed to create temp FrontBuffer surface.\n");
770 ID3DPresent_FrontBufferCopy(This
->present
, temp_handle
);
772 NineSurface9_CopySurface(dest_surface
, temp_surface
, NULL
, NULL
);
774 ID3DPresent_DestroyD3DWindowBuffer(This
->present
, temp_handle
);
775 NineUnknown_Destroy(NineUnknown(temp_surface
));
781 NineSwapChain9_GetBackBuffer( struct NineSwapChain9
*This
,
783 D3DBACKBUFFER_TYPE Type
,
784 IDirect3DSurface9
**ppBackBuffer
)
786 DBG("GetBackBuffer: This=%p iBackBuffer=%d Type=%d ppBackBuffer=%p\n",
787 This
, iBackBuffer
, Type
, ppBackBuffer
);
788 (void)user_error(Type
== D3DBACKBUFFER_TYPE_MONO
);
789 user_assert(iBackBuffer
< This
->params
.BackBufferCount
, D3DERR_INVALIDCALL
);
790 user_assert(ppBackBuffer
!= NULL
, E_POINTER
);
792 NineUnknown_AddRef(NineUnknown(This
->buffers
[iBackBuffer
]));
793 *ppBackBuffer
= (IDirect3DSurface9
*)This
->buffers
[iBackBuffer
];
798 NineSwapChain9_GetRasterStatus( struct NineSwapChain9
*This
,
799 D3DRASTER_STATUS
*pRasterStatus
)
801 DBG("GetRasterStatus: This=%p pRasterStatus=%p\n",
802 This
, pRasterStatus
);
803 user_assert(pRasterStatus
!= NULL
, E_POINTER
);
804 return ID3DPresent_GetRasterStatus(This
->present
, pRasterStatus
);
808 NineSwapChain9_GetDisplayMode( struct NineSwapChain9
*This
,
809 D3DDISPLAYMODE
*pMode
)
811 D3DDISPLAYMODEEX mode
;
812 D3DDISPLAYROTATION rot
;
815 DBG("GetDisplayMode: This=%p pMode=%p\n",
817 user_assert(pMode
!= NULL
, E_POINTER
);
819 hr
= ID3DPresent_GetDisplayMode(This
->present
, &mode
, &rot
);
821 pMode
->Width
= mode
.Width
;
822 pMode
->Height
= mode
.Height
;
823 pMode
->RefreshRate
= mode
.RefreshRate
;
824 pMode
->Format
= mode
.Format
;
830 NineSwapChain9_GetPresentParameters( struct NineSwapChain9
*This
,
831 D3DPRESENT_PARAMETERS
*pPresentationParameters
)
833 DBG("GetPresentParameters: This=%p pPresentationParameters=%p\n",
834 This
, pPresentationParameters
);
835 user_assert(pPresentationParameters
!= NULL
, E_POINTER
);
836 *pPresentationParameters
= This
->params
;
840 IDirect3DSwapChain9Vtbl NineSwapChain9_vtable
= {
841 (void *)NineUnknown_QueryInterface
,
842 (void *)NineUnknown_AddRef
,
843 (void *)NineUnknown_Release
,
844 (void *)NineSwapChain9_Present
,
845 (void *)NineSwapChain9_GetFrontBufferData
,
846 (void *)NineSwapChain9_GetBackBuffer
,
847 (void *)NineSwapChain9_GetRasterStatus
,
848 (void *)NineSwapChain9_GetDisplayMode
,
849 (void *)NineUnknown_GetDevice
, /* actually part of SwapChain9 iface */
850 (void *)NineSwapChain9_GetPresentParameters
853 static const GUID
*NineSwapChain9_IIDs
[] = {
854 &IID_IDirect3DSwapChain9
,
860 NineSwapChain9_new( struct NineDevice9
*pDevice
,
862 ID3DPresent
*pPresent
,
863 D3DPRESENT_PARAMETERS
*pPresentationParameters
,
864 struct d3dadapter9_context
*pCTX
,
866 struct NineSwapChain9
**ppOut
)
868 NINE_DEVICE_CHILD_NEW(SwapChain9
, ppOut
, pDevice
, /* args */
869 implicit
, pPresent
, pPresentationParameters
,
870 pCTX
, hFocusWindow
, NULL
);