#include "nine_pipe.h"
#include "nine_dump.h"
+#include "util/u_atomic.h"
#include "util/u_inlines.h"
#include "util/u_surface.h"
#include "hud/hud_context.h"
D3DDISPLAYMODEEX *mode )
{
HRESULT hr;
+ int i;
DBG("This=%p pDevice=%p pPresent=%p pCTX=%p hFocusWindow=%p\n",
This, pParams->device, pPresent, pCTX, hFocusWindow);
This->mode = NULL;
ID3DPresent_AddRef(pPresent);
- if (!This->actx->thread_submit &&
- This->base.device->minor_version_num > 2) {
+ if (This->base.device->minor_version_num > 2) {
D3DPRESENT_PARAMETERS2 params2;
memset(¶ms2, 0, sizeof(D3DPRESENT_PARAMETERS2));
This->rendering_done = FALSE;
This->pool = NULL;
+ for (i = 0; i < D3DPRESENT_BACK_BUFFERS_MAX_EX + 1; i++) {
+ This->pending_presentation[i] = calloc(1, sizeof(BOOL));
+ if (!This->pending_presentation[i])
+ return E_OUTOFMEMORY;
+ }
return NineSwapChain9_Resize(This, pPresentationParameters, mode);
}
if (This->pool)
_mesa_threadpool_destroy(This, This->pool);
+ for (i = 0; i < D3DPRESENT_BACK_BUFFERS_MAX_EX + 1; i++) {
+ if (This->pending_presentation[i])
+ FREE(This->pending_presentation[i]);
+ }
+
for (i = 0; i < This->num_back_buffers; i++) {
if (This->buffers[i])
NineUnknown_Detach(NineUnknown(This->buffers[i]));
struct pipe_fence_handle *fence_to_wait;
ID3DPresent *present;
D3DWindowBuffer *present_handle;
+ BOOL *pending_presentation;
HWND hDestWindowOverride;
};
work->screen->fence_reference(work->screen, &(work->fence_to_wait), NULL);
}
ID3DPresent_PresentBuffer(work->present, work->present_handle, work->hDestWindowOverride, NULL, NULL, NULL, 0);
+ p_atomic_set(work->pending_presentation, FALSE);
free(work);
}
work->present = This->present;
work->present_handle = This->present_handles[0];
work->hDestWindowOverride = hDestWindowOverride;
+ work->pending_presentation = This->pending_presentation[0];
+ p_atomic_set(work->pending_presentation, TRUE);
This->tasks[0] = _mesa_threadpool_queue_task(This->pool, work_present, work);
return;
struct pipe_resource *res = NULL;
D3DWindowBuffer *handle_temp;
struct threadpool_task *task_temp;
+ BOOL *pending_presentation_temp;
int i;
HRESULT hr;
if (This->base.device->minor_version_num > 2 &&
This->params.SwapEffect == D3DSWAPEFFECT_DISCARD &&
- This->params.PresentationInterval == D3DPRESENT_INTERVAL_IMMEDIATE &&
- !This->actx->thread_submit) {
+ This->params.PresentationInterval == D3DPRESENT_INTERVAL_IMMEDIATE) {
int next_buffer = -1;
while (next_buffer == -1) {
/* Find a free backbuffer */
for (i = 1; i < This->num_back_buffers; i++) {
- if (ID3DPresent_IsBufferReleased(This->present, This->present_handles[i])) {
+ if (!p_atomic_read(This->pending_presentation[i]) &&
+ ID3DPresent_IsBufferReleased(This->present, This->present_handles[i])) {
DBG("Found buffer released: %d\n", i);
next_buffer = i;
break;
ID3DPresent_WaitBufferReleaseEvent(This->present);
}
}
+
+ /* Free the task (we already checked it is finished) */
+ if (This->tasks[next_buffer])
+ _mesa_threadpool_wait_for_task(This->pool, &(This->tasks[next_buffer]));
+ assert(!*This->pending_presentation[next_buffer] && !This->tasks[next_buffer]);
+ This->tasks[next_buffer] = This->tasks[0];
+ This->tasks[0] = NULL;
+ pending_presentation_temp = This->pending_presentation[next_buffer];
+ This->pending_presentation[next_buffer] = This->pending_presentation[0];
+ This->pending_presentation[0] = pending_presentation_temp;
+
/* Switch with the released buffer */
pipe_resource_reference(&res, This->buffers[0]->base.resource);
NineSurface9_SetResourceResize(
handle_temp = This->present_handles[0];
This->present_handles[0] = This->present_handles[next_buffer];
This->present_handles[next_buffer] = handle_temp;
-
- /* Path not yet compatible with thread_submit */
- assert(!This->tasks[0] && !This->tasks[next_buffer]);
} else {
switch (This->params.SwapEffect) {
case D3DSWAPEFFECT_OVERLAY: /* Not implemented, fallback to FLIP */
This->tasks[i-1] = This->tasks[i];
}
This->tasks[This->num_back_buffers - 1] = task_temp;
+ pending_presentation_temp = This->pending_presentation[0];
+ for (i = 1; i < This->num_back_buffers; i++) {
+ This->pending_presentation[i-1] = This->pending_presentation[i];
+ }
+ This->pending_presentation[This->num_back_buffers - 1] = pending_presentation_temp;
break;
case D3DSWAPEFFECT_COPY:
if (This->tasks[0])
_mesa_threadpool_wait_for_task(This->pool, &(This->tasks[0]));
+ assert(!*This->pending_presentation[0]);
ID3DPresent_WaitBufferReleased(This->present, This->present_handles[0]);
}
* without releasing them:
* . Buffer on screen.
* . Buffer scheduled kernel side to be next on screen.
- * . Last buffer sent.
- * For some reasons, 5 buffers are actually needed, because in
- * case a pageflip is missed because rendering wasn't finished,
- * the Xserver will hold 4 buffers. */
- if (!This->actx->thread_submit &&
- This->base.device->minor_version_num > 2 &&
- pParams->PresentationInterval == D3DPRESENT_INTERVAL_IMMEDIATE &&
- count < 5)
- count = 5;
+ * . Last buffer sent. */
+ if (This->base.device->minor_version_num > 2 &&
+ pParams->PresentationInterval == D3DPRESENT_INTERVAL_IMMEDIATE) {
+ if (This->actx->thread_submit && count < 4)
+ count = 4;
+ /* When thread_submit is not used, 5 buffers are actually needed,
+ * because in case a pageflip is missed because rendering wasn't finished,
+ * the Xserver will hold 4 buffers. */
+ else if (!This->actx->thread_submit && count < 5)
+ count = 5;
+ }
}
return count;