boolean resource_surface_flush(struct resource_surface *rsurf, struct native_display *ndpy) { struct pipe_fence_handle *fence = NULL; struct pipe_screen *screen = rsurf->screen; struct pipe_context *pipe= ndpy_get_copy_context(ndpy); if (!pipe) return FALSE; pipe->flush(pipe, &fence, 0); if (fence == NULL) return FALSE; swap_fences_push_back(rsurf, fence); screen->fence_reference(screen, &fence, NULL); return TRUE; }
static inline HRESULT present( struct NineSwapChain9 *This, const RECT *pSourceRect, const RECT *pDestRect, HWND hDestWindowOverride, const RGNDATA *pDirtyRegion, DWORD dwFlags ) { struct pipe_context *pipe; struct pipe_resource *resource; struct pipe_fence_handle *fence; HRESULT hr; struct pipe_blit_info blit; DBG("present: This=%p pSourceRect=%p pDestRect=%p " "pDirtyRegion=%p hDestWindowOverride=%p" "dwFlags=%d resource=%p\n", This, pSourceRect, pDestRect, pDirtyRegion, hDestWindowOverride, (int)dwFlags, This->buffers[0]->base.resource); if (pSourceRect) DBG("pSourceRect = (%u..%u)x(%u..%u)\n", pSourceRect->left, pSourceRect->right, pSourceRect->top, pSourceRect->bottom); if (pDestRect) DBG("pDestRect = (%u..%u)x(%u..%u)\n", pDestRect->left, pDestRect->right, pDestRect->top, pDestRect->bottom); /* TODO: in the case the source and destination rect have different size: * We need to allocate a new buffer, and do a blit to it to resize. * We can't use the present_buffer for that since when we created it, * we couldn't guess which size would have been needed. * If pDestRect or pSourceRect is null, we have to check the sizes * from the source size, and the destination window size. * In this case, either resize rngdata, or pass NULL instead */ /* Note: This->buffers[0]->level should always be 0 */ if (This->rendering_done) goto bypass_rendering; resource = This->buffers[0]->base.resource; if (This->params.SwapEffect == D3DSWAPEFFECT_DISCARD) handle_draw_cursor_and_hud(This, resource); pipe = NineDevice9_GetPipe(This->base.device); if (This->present_buffers[0]) { memset(&blit, 0, sizeof(blit)); blit.src.resource = resource; blit.src.level = 0; blit.src.format = resource->format; blit.src.box.z = 0; blit.src.box.depth = 1; blit.src.box.x = 0; blit.src.box.y = 0; blit.src.box.width = resource->width0; blit.src.box.height = resource->height0; resource = This->present_buffers[0]; blit.dst.resource = resource; blit.dst.level = 0; blit.dst.format = resource->format; blit.dst.box.z = 0; blit.dst.box.depth = 1; blit.dst.box.x = 0; blit.dst.box.y = 0; blit.dst.box.width = resource->width0; blit.dst.box.height = resource->height0; blit.mask = PIPE_MASK_RGBA; blit.filter = PIPE_TEX_FILTER_NEAREST; blit.scissor_enable = FALSE; blit.alpha_blend = FALSE; pipe->blit(pipe, &blit); } /* The resource we present has to resolve fast clears * if needed (and other things) */ pipe->flush_resource(pipe, resource); if (This->params.SwapEffect != D3DSWAPEFFECT_DISCARD) handle_draw_cursor_and_hud(This, resource); fence = NULL; pipe->flush(pipe, &fence, PIPE_FLUSH_END_OF_FRAME); if (fence) { swap_fences_push_back(This, fence); This->screen->fence_reference(This->screen, &fence, NULL); } This->rendering_done = TRUE; bypass_rendering: if (dwFlags & D3DPRESENT_DONOTWAIT) { UNTESTED(2); BOOL still_draw = FALSE; fence = swap_fences_see_front(This); if (fence) { still_draw = !This->screen->fence_finish(This->screen, NULL, fence, 0); This->screen->fence_reference(This->screen, &fence, NULL); } if (still_draw) return D3DERR_WASSTILLDRAWING; } if (!This->enable_threadpool) { This->tasks[0]=NULL; fence = swap_fences_pop_front(This); if (fence) { (void) This->screen->fence_finish(This->screen, NULL, fence, PIPE_TIMEOUT_INFINITE); This->screen->fence_reference(This->screen, &fence, NULL); } hr = ID3DPresent_PresentBuffer(This->present, This->present_handles[0], hDestWindowOverride, pSourceRect, pDestRect, pDirtyRegion, dwFlags); if (FAILED(hr)) { UNTESTED(3);return hr; } } else { pend_present(This, hDestWindowOverride); } This->rendering_done = FALSE; return D3D_OK; }
/** * DRI2 flush extension, the flush_with_flags function. * * \param context the context * \param drawable the drawable to flush * \param flags a combination of _DRI2_FLUSH_xxx flags * \param throttle_reason the reason for throttling, 0 = no throttling */ void dri_flush(__DRIcontext *cPriv, __DRIdrawable *dPriv, unsigned flags, enum __DRI2throttleReason reason) { struct dri_context *ctx = dri_context(cPriv); struct dri_drawable *drawable = dri_drawable(dPriv); unsigned flush_flags; boolean swap_msaa_buffers = FALSE; if (!ctx) { assert(0); return; } if (drawable) { /* prevent recursion */ if (drawable->flushing) return; drawable->flushing = TRUE; } else { flags &= ~__DRI2_FLUSH_DRAWABLE; } /* Flush the drawable. */ if ((flags & __DRI2_FLUSH_DRAWABLE) && drawable->textures[ST_ATTACHMENT_BACK_LEFT]) { struct pipe_context *pipe = ctx->st->pipe; if (drawable->stvis.samples > 1 && reason == __DRI2_THROTTLE_SWAPBUFFER) { /* Resolve the MSAA back buffer. */ dri_pipe_blit(ctx->st->pipe, drawable->textures[ST_ATTACHMENT_BACK_LEFT], drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]); if (drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT] && drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]) { swap_msaa_buffers = TRUE; } /* FRONT_LEFT is resolved in drawable->flush_frontbuffer. */ } dri_postprocessing(ctx, drawable, ST_ATTACHMENT_BACK_LEFT); if (ctx->hud) { hud_draw(ctx->hud, drawable->textures[ST_ATTACHMENT_BACK_LEFT]); } pipe->flush_resource(pipe, drawable->textures[ST_ATTACHMENT_BACK_LEFT]); } flush_flags = 0; if (flags & __DRI2_FLUSH_CONTEXT) flush_flags |= ST_FLUSH_FRONT; if (reason == __DRI2_THROTTLE_SWAPBUFFER) flush_flags |= ST_FLUSH_END_OF_FRAME; /* Flush the context and throttle if needed. */ if (dri_screen(ctx->sPriv)->throttling_enabled && drawable && (reason == __DRI2_THROTTLE_SWAPBUFFER || reason == __DRI2_THROTTLE_FLUSHFRONT)) { /* Throttle. * * This pulls a fence off the throttling queue and waits for it if the * number of fences on the throttling queue has reached the desired * number. * * Then flushes to insert a fence at the current rendering position, and * pushes that fence on the queue. This requires that the st_context_iface * flush method returns a fence even if there are no commands to flush. */ struct pipe_screen *screen = drawable->screen->base.screen; struct pipe_fence_handle *fence; fence = swap_fences_pop_front(drawable); if (fence) { (void) screen->fence_finish(screen, fence, PIPE_TIMEOUT_INFINITE); screen->fence_reference(screen, &fence, NULL); } ctx->st->flush(ctx->st, flush_flags, &fence); if (fence) { swap_fences_push_back(drawable, fence); screen->fence_reference(screen, &fence, NULL); } } else if (flags & (__DRI2_FLUSH_DRAWABLE | __DRI2_FLUSH_CONTEXT)) { ctx->st->flush(ctx->st, flush_flags, NULL); } if (drawable) { drawable->flushing = FALSE; } /* Swap the MSAA front and back buffers, so that reading * from the front buffer after SwapBuffers returns what was * in the back buffer. */ if (swap_msaa_buffers) { struct pipe_resource *tmp = drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT]; drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT] = drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]; drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT] = tmp; /* Now that we have swapped the buffers, this tells the state * tracker to revalidate the framebuffer. */ p_atomic_inc(&drawable->base.stamp); } }