From d8e66aca8443c6802ecd8f1a353024ed1d0f32c3 Mon Sep 17 00:00:00 2001 From: Brian Date: Thu, 1 Nov 2007 18:37:00 -0600 Subject: [PATCH] Start re-working SwapBuffers. intelCopyBuffer() is now intelDisplayBuffer(): it displays the given surface in the on-screen window. Added a pipe_surface parameter to winsys->flush_frontbuffer(). Front buffer rendering/flushing actually works now. But, we should only allocate the front surface on demand... --- .../dri/intel_winsys/intel_swapbuffers.c | 79 ++++++++++--------- .../dri/intel_winsys/intel_swapbuffers.h | 5 +- .../dri/intel_winsys/intel_winsys_pipe.c | 7 +- src/mesa/pipe/p_winsys.h | 4 +- src/mesa/pipe/xlib/xm_winsys.c | 14 ++-- src/mesa/state_tracker/st_cb_flush.c | 7 +- 6 files changed, 64 insertions(+), 52 deletions(-) diff --git a/src/mesa/drivers/dri/intel_winsys/intel_swapbuffers.c b/src/mesa/drivers/dri/intel_winsys/intel_swapbuffers.c index 2ffc757469e..350c3f38a22 100644 --- a/src/mesa/drivers/dri/intel_winsys/intel_swapbuffers.c +++ b/src/mesa/drivers/dri/intel_winsys/intel_swapbuffers.c @@ -58,15 +58,33 @@ typedef struct drm_i915_flip { #endif +/** + * Return the pipe_surface for the given renderbuffer. + */ +static struct pipe_surface * +get_color_surface(struct intel_framebuffer *intel_fb, + GLuint bufferIndex) +{ + struct st_renderbuffer *strb + = st_renderbuffer(intel_fb->Base.Attachment[bufferIndex].Renderbuffer); + if (strb) + return strb->surface; + return NULL; +} /** - * Copy the back color buffer to the front color buffer. - * Used for SwapBuffers(). + * Display a colorbuffer surface in an X window. + * Used for SwapBuffers and flushing front buffer rendering. + * + * \param dPriv the window/drawable to display into + * \param surf the surface to display + * \param rect optional subrect of surface to display (may be NULL). */ void -intelCopyBuffer(__DRIdrawablePrivate * dPriv, - const drm_clip_rect_t * rect) +intelDisplayBuffer(__DRIdrawablePrivate * dPriv, + struct pipe_surface *surf, + const drm_clip_rect_t * rect) { struct intel_context *intel; @@ -103,49 +121,24 @@ intelCopyBuffer(__DRIdrawablePrivate * dPriv, if (dPriv && dPriv->numClipRects) { struct intel_framebuffer *intel_fb = dPriv->driverPrivate; -#if 0 - const struct pipe_region *backRegion - = intel_fb->Base._ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT ? - intel_get_rb_region(&intel_fb->Base, BUFFER_FRONT_LEFT) : - intel_get_rb_region(&intel_fb->Base, BUFFER_BACK_LEFT); -#endif const int backWidth = intel_fb->Base.Width; const int backHeight = intel_fb->Base.Height; const int nbox = dPriv->numClipRects; const drm_clip_rect_t *pbox = dPriv->pClipRects; const int pitch = intelScreen->front.pitch / intelScreen->front.cpp; -#if 0 - const int srcpitch = backRegion->pitch; -#endif const int cpp = intelScreen->front.cpp; int BR13, CMD; int i; - - const struct pipe_surface *backSurf; - const struct pipe_region *backRegion; - int srcpitch; - struct st_renderbuffer *strb; - - /* blit from back color buffer if it exists, else front buffer */ - strb = st_renderbuffer(intel_fb->Base.Attachment[BUFFER_BACK_LEFT].Renderbuffer); - if (strb) { - backSurf = strb->surface; - } - else { - strb = st_renderbuffer(intel_fb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer); - backSurf = strb->surface; - } - - backRegion = backSurf->region; - srcpitch = backRegion->pitch; + const struct pipe_region *srcRegion = surf->region; + const int srcpitch= srcRegion->pitch; ASSERT(intel_fb); ASSERT(intel_fb->Base.Name == 0); /* Not a user-created FBO */ - ASSERT(backRegion); - ASSERT(backRegion->cpp == cpp); + ASSERT(srcRegion); + ASSERT(srcRegion->cpp == cpp); DBG(SWAP, "front pitch %d back pitch %d\n", - pitch, backRegion->pitch); + pitch, srcRegion->pitch); if (cpp == 2) { BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24); @@ -164,12 +157,15 @@ intelCopyBuffer(__DRIdrawablePrivate * dPriv, if (pbox->x1 > pbox->x2 || pbox->y1 > pbox->y2 || pbox->x2 > intelScreen->front.width || - pbox->y2 > intelScreen->front.height) + pbox->y2 > intelScreen->front.height) { + /* invalid cliprect, skip it */ continue; + } box = *pbox; if (rect) { + /* intersect cliprect with user-provided src rect */ drm_clip_rect_t rrect; rrect.x1 = dPriv->x + rect->x1; @@ -212,7 +208,7 @@ intelCopyBuffer(__DRIdrawablePrivate * dPriv, DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, 0); OUT_BATCH((sbox.y1 << 16) | sbox.x1); OUT_BATCH((srcpitch * cpp) & 0xffff); - OUT_RELOC(dri_bo(backRegion->buffer), + OUT_RELOC(dri_bo(srcRegion->buffer), DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, 0); @@ -590,10 +586,13 @@ intelSwapBuffers(__DRIdrawablePrivate * dPriv) _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */ if (!intelScheduleSwap(dPriv, &missed_target)) { + struct pipe_surface *back_surf + = get_color_surface(intel_fb, BUFFER_BACK_LEFT); + driWaitForVBlank(dPriv, &intel_fb->vbl_seq, intel_fb->vblank_flags, &missed_target); - intelCopyBuffer(dPriv, NULL); + intelDisplayBuffer(dPriv, back_surf, NULL); } intel_fb->swap_count++; @@ -621,6 +620,10 @@ intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h) GLcontext *ctx = intel->st->ctx; if (ctx->Visual.doubleBufferMode) { + struct intel_framebuffer *intel_fb = dPriv->driverPrivate; + struct pipe_surface *back_surf + = get_color_surface(intel_fb, BUFFER_BACK_LEFT); + drm_clip_rect_t rect; /* fixup cliprect (driDrawable may have changed?) later */ rect.x1 = x; @@ -628,7 +631,7 @@ intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h) rect.x2 = w; rect.y2 = h; _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */ - intelCopyBuffer(dPriv, &rect); + intelDisplayBuffer(dPriv, back_surf, &rect); } } else { diff --git a/src/mesa/drivers/dri/intel_winsys/intel_swapbuffers.h b/src/mesa/drivers/dri/intel_winsys/intel_swapbuffers.h index 0065eac9b2b..15ed6704d23 100644 --- a/src/mesa/drivers/dri/intel_winsys/intel_swapbuffers.h +++ b/src/mesa/drivers/dri/intel_winsys/intel_swapbuffers.h @@ -62,8 +62,9 @@ struct intel_framebuffer }; -void intelCopyBuffer(__DRIdrawablePrivate * dPriv, - const drm_clip_rect_t * rect); +extern void intelDisplayBuffer(__DRIdrawablePrivate * dPriv, + struct pipe_surface *surf, + const drm_clip_rect_t * rect); extern void intel_wait_flips(struct intel_context *intel, GLuint batch_flags); diff --git a/src/mesa/drivers/dri/intel_winsys/intel_winsys_pipe.c b/src/mesa/drivers/dri/intel_winsys/intel_winsys_pipe.c index 4569b1e3bf6..7f788b8537e 100644 --- a/src/mesa/drivers/dri/intel_winsys/intel_winsys_pipe.c +++ b/src/mesa/drivers/dri/intel_winsys/intel_winsys_pipe.c @@ -185,12 +185,13 @@ static void intel_wait_idle( struct pipe_winsys *sws ) * we copied its contents to the real frontbuffer. Our task is easy: */ static void -intel_flush_frontbuffer( struct pipe_winsys *sws ) +intel_flush_frontbuffer( struct pipe_winsys *sws, + struct pipe_surface *surf ) { struct intel_context *intel = intel_pipe_winsys(sws)->intel; __DRIdrawablePrivate *dPriv = intel->driDrawable; - - intelCopyBuffer(dPriv, NULL); + + intelDisplayBuffer(dPriv, surf, NULL); } diff --git a/src/mesa/pipe/p_winsys.h b/src/mesa/pipe/p_winsys.h index 10a2caf1a24..2d4432dbca4 100644 --- a/src/mesa/pipe/p_winsys.h +++ b/src/mesa/pipe/p_winsys.h @@ -53,6 +53,7 @@ struct pipe_buffer_handle; struct pipe_region; +struct pipe_surface; /** Opaque type */ struct pipe_buffer_handle; @@ -63,7 +64,8 @@ struct pipe_winsys * Do any special operations to ensure frontbuffer contents are * displayed, eg copy fake frontbuffer. */ - void (*flush_frontbuffer)( struct pipe_winsys *sws ); + void (*flush_frontbuffer)( struct pipe_winsys *sws, + struct pipe_surface *surf ); /** Debug output */ void (*printf)( struct pipe_winsys *sws, diff --git a/src/mesa/pipe/xlib/xm_winsys.c b/src/mesa/pipe/xlib/xm_winsys.c index e6e98ed3960..5de811a66fa 100644 --- a/src/mesa/pipe/xlib/xm_winsys.c +++ b/src/mesa/pipe/xlib/xm_winsys.c @@ -157,14 +157,14 @@ xm_buffer_get_subdata(struct pipe_winsys *pws, struct pipe_buffer_handle *buf, } static void -xm_flush_frontbuffer(struct pipe_winsys *pws) +xm_flush_frontbuffer(struct pipe_winsys *pws, + struct pipe_surface *surf ) { - /* - struct intel_context *intel = intel_pipe_winsys(sws)->intel; - __DRIdrawablePrivate *dPriv = intel->driDrawable; - - intelCopyBuffer(dPriv, NULL); - */ + /* The Xlib driver's front color surfaces are actually X Windows so + * this flush is a no-op. + * If we instead did front buffer rendering to a temporary XImage, + * this would be the place to copy the Ximage to the on-screen Window. + */ } static void diff --git a/src/mesa/state_tracker/st_cb_flush.c b/src/mesa/state_tracker/st_cb_flush.c index 41f21c361cd..c2c3c80b875 100644 --- a/src/mesa/state_tracker/st_cb_flush.c +++ b/src/mesa/state_tracker/st_cb_flush.c @@ -35,6 +35,7 @@ #include "main/macros.h" #include "st_context.h" #include "st_cb_flush.h" +#include "st_cb_fbo.h" #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_winsys.h" @@ -59,9 +60,13 @@ static void st_flush(GLcontext *ctx) if (st->flags.frontbuffer_dirty) { + struct st_renderbuffer *strb + = st_renderbuffer(ctx->DrawBuffer->Attachment[BUFFER_FRONT_LEFT].Renderbuffer); + struct pipe_surface *front_surf = strb->surface; + /* Hook for copying "fake" frontbuffer if necessary: */ - st->pipe->winsys->flush_frontbuffer( st->pipe->winsys ); + st->pipe->winsys->flush_frontbuffer( st->pipe->winsys, front_surf ); st->flags.frontbuffer_dirty = 0; } } -- 2.30.2