diff options
Diffstat (limited to 'src/mesa/drivers')
| -rw-r--r-- | src/mesa/drivers/dri/i915tex/intel_blit.c | 253 | ||||
| -rw-r--r-- | src/mesa/drivers/dri/i915tex/intel_buffers.c | 352 | ||||
| -rw-r--r-- | src/mesa/drivers/dri/i915tex/intel_buffers.h | 3 | ||||
| -rw-r--r-- | src/mesa/drivers/dri/i915tex/intel_context.c | 78 | ||||
| -rw-r--r-- | src/mesa/drivers/dri/i915tex/intel_context.h | 14 | ||||
| -rw-r--r-- | src/mesa/drivers/dri/i915tex/intel_fbo.c | 46 | ||||
| -rw-r--r-- | src/mesa/drivers/dri/i915tex/intel_fbo.h | 35 | ||||
| -rw-r--r-- | src/mesa/drivers/dri/i915tex/intel_reg.h | 4 | ||||
| -rw-r--r-- | src/mesa/drivers/dri/i915tex/intel_screen.c | 111 | ||||
| -rw-r--r-- | src/mesa/drivers/dri/i915tex/intel_screen.h | 2 | ||||
| -rw-r--r-- | src/mesa/drivers/dri/i915tex/intel_tris.c | 2 | ||||
| -rw-r--r-- | src/mesa/drivers/dri/i915tex/server/i830_common.h | 6 | 
12 files changed, 605 insertions, 301 deletions
diff --git a/src/mesa/drivers/dri/i915tex/intel_blit.c b/src/mesa/drivers/dri/i915tex/intel_blit.c index 550669ab0c..dbe4ba2ac5 100644 --- a/src/mesa/drivers/dri/i915tex/intel_blit.c +++ b/src/mesa/drivers/dri/i915tex/intel_blit.c @@ -55,8 +55,6 @@ intelCopyBuffer(const __DRIdrawablePrivate * dPriv,     struct intel_context *intel;     const intelScreenPrivate *intelScreen; -   GLboolean missed_target; -   int64_t ust;     DBG("%s\n", __FUNCTION__); @@ -68,41 +66,6 @@ intelCopyBuffer(const __DRIdrawablePrivate * dPriv,     intelScreen = intel->intelScreen; -   if (!rect && !intel->swap_scheduled && intelScreen->drmMinor >= 6 && -	!(intel->vblank_flags & VBLANK_FLAG_NO_IRQ) && -	intelScreen->current_rotation == 0) { -      unsigned int interval = driGetVBlankInterval(dPriv, intel->vblank_flags); -      unsigned int target; -      drm_i915_vblank_swap_t swap; -  -      swap.drawable = dPriv->hHWDrawable; -      swap.seqtype = DRM_VBLANK_ABSOLUTE; -      target = swap.sequence = intel->vbl_seq + interval; - -      if (intel->vblank_flags & VBLANK_FLAG_SYNC) { -	 swap.seqtype |= DRM_VBLANK_NEXTONMISS; -      } else if (interval == 0) { -	 goto noschedule; -      } - -      if ( intel->vblank_flags & VBLANK_FLAG_SECONDARY ) { -	 swap.seqtype |= DRM_VBLANK_SECONDARY; -      } - -      intel_batchbuffer_flush(intel->batch); - -      if (!drmCommandWriteRead(intel->driFd, DRM_I915_VBLANK_SWAP, &swap, -			       sizeof(swap))) { -	 intel->swap_scheduled = 1; -	 intel->vbl_seq = swap.sequence; -	 swap.sequence -= target; -	 missed_target = swap.sequence > 0 && swap.sequence <= (1 << 23); -      } -   } else { -      intel->swap_scheduled = 0; -   } -noschedule: -       if (intel->last_swap_fence) {        driFenceFinish(intel->last_swap_fence, DRM_FENCE_TYPE_EXE, GL_TRUE);        driFenceUnReference(intel->last_swap_fence); @@ -111,122 +74,88 @@ noschedule:     intel->last_swap_fence = intel->first_swap_fence;     intel->first_swap_fence = NULL; -   if (!intel->swap_scheduled) { -      if (!rect) { -	 driWaitForVBlank(dPriv, &intel->vbl_seq, intel->vblank_flags, -			  &missed_target); -      } - - -      /* The LOCK_HARDWARE is required for the cliprects.  Buffer offsets -       * should work regardless. -       */ -      LOCK_HARDWARE(intel); - -      if (intel->driDrawable && intel->driDrawable->numClipRects) { -	 const intelScreenPrivate *intelScreen = intel->intelScreen; -	 struct gl_framebuffer *fb -	    = (struct gl_framebuffer *) dPriv->driverPrivate; -	 const struct intel_region *frontRegion -	    = intel_get_rb_region(fb, BUFFER_FRONT_LEFT); -	 const struct intel_region *backRegion -	    = intel_get_rb_region(fb, BUFFER_BACK_LEFT); -	 const int nbox = dPriv->numClipRects; -	 const drm_clip_rect_t *pbox = dPriv->pClipRects; -	 const int pitch = frontRegion->pitch; -	 const int cpp = frontRegion->cpp; -	 int BR13, CMD; -	 int i; - -	 ASSERT(fb); -	 ASSERT(fb->Name == 0);    /* Not a user-created FBO */ -	 ASSERT(frontRegion); -	 ASSERT(backRegion); -	 ASSERT(frontRegion->pitch == backRegion->pitch); -	 ASSERT(frontRegion->cpp == backRegion->cpp); - -	 if (cpp == 2) { -	    BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24); -	    CMD = XY_SRC_COPY_BLT_CMD; -	 } -	 else { -	    BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24) | (1 << 25); -	    CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | -		   XY_SRC_COPY_BLT_WRITE_RGB); -	 } - -	 for (i = 0; i < nbox; i++, pbox++) { -	    drm_clip_rect_t box; +   /* The LOCK_HARDWARE is required for the cliprects.  Buffer offsets +    * should work regardless. +    */ +   LOCK_HARDWARE(intel); -	    if (pbox->x1 > pbox->x2 || -		pbox->y1 > pbox->y2 || -		pbox->x2 > intelScreen->width || pbox->y2 > intelScreen->height) -	       continue; +   if (dPriv && dPriv->numClipRects) { +      struct intel_framebuffer *intel_fb = dPriv->driverPrivate; +      const struct intel_region *frontRegion +	 = intel_get_rb_region(&intel_fb->Base, BUFFER_FRONT_LEFT); +      const struct intel_region *backRegion +	 = intel_get_rb_region(&intel_fb->Base, BUFFER_BACK_LEFT); +      const int nbox = dPriv->numClipRects; +      const drm_clip_rect_t *pbox = dPriv->pClipRects; +      const int pitch = frontRegion->pitch; +      const int cpp = frontRegion->cpp; +      int BR13, CMD; +      int i; -	    box = *pbox; +      ASSERT(intel_fb); +      ASSERT(intel_fb->Base.Name == 0);    /* Not a user-created FBO */ +      ASSERT(frontRegion); +      ASSERT(backRegion); +      ASSERT(frontRegion->pitch == backRegion->pitch); +      ASSERT(frontRegion->cpp == backRegion->cpp); -	    if (rect) { -	       if (rect->x1 > box.x1) -		  box.x1 = rect->x1; -	       if (rect->y1 > box.y1) -		  box.y1 = rect->y1; -	       if (rect->x2 < box.x2) -		  box.x2 = rect->x2; -	       if (rect->y2 < box.y2) -		  box.y2 = rect->y2; +      if (cpp == 2) { +	 BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24); +	 CMD = XY_SRC_COPY_BLT_CMD; +      } +      else { +	 BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24) | (1 << 25); +	 CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | +		XY_SRC_COPY_BLT_WRITE_RGB); +      } -	       if (box.x1 > box.x2 || box.y1 > box.y2) -		  continue; -	    } +      for (i = 0; i < nbox; i++, pbox++) { +	 drm_clip_rect_t box; -	    BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS); -	    OUT_BATCH(CMD); -	    OUT_BATCH(BR13); -	    OUT_BATCH((pbox->y1 << 16) | pbox->x1); -	    OUT_BATCH((pbox->y2 << 16) | pbox->x2); +	 if (pbox->x1 > pbox->x2 || +	     pbox->y1 > pbox->y2 || +	     pbox->x2 > intelScreen->width || pbox->y2 > intelScreen->height) +	    continue; -	    if (intel->sarea->pf_current_page == 0) -	       OUT_RELOC(frontRegion->buffer, -			 DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, -			 DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, 0); -	    else -	       OUT_RELOC(backRegion->buffer, -			 DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, -			 DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, 0); -	    OUT_BATCH((pbox->y1 << 16) | pbox->x1); -	    OUT_BATCH(BR13 & 0xffff); +	 box = *pbox; -	    if (intel->sarea->pf_current_page == 0) -	       OUT_RELOC(backRegion->buffer, -			 DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, -			 DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, 0); -	    else -	       OUT_RELOC(frontRegion->buffer, -			 DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, -			 DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, 0); +	 if (rect) { +	    if (rect->x1 > box.x1) +	       box.x1 = rect->x1; +	    if (rect->y1 > box.y1) +	       box.y1 = rect->y1; +	    if (rect->x2 < box.x2) +	       box.x2 = rect->x2; +	    if (rect->y2 < box.y2) +	       box.y2 = rect->y2; -	    ADVANCE_BATCH(); +	    if (box.x1 > box.x2 || box.y1 > box.y2) +	       continue;  	 } -	 if (intel->first_swap_fence) -	    driFenceUnReference(intel->first_swap_fence); -	 intel->first_swap_fence = intel_batchbuffer_flush(intel->batch); -	 driFenceReference(intel->first_swap_fence); -      } +	 BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS); +	 OUT_BATCH(CMD); +	 OUT_BATCH(BR13); +	 OUT_BATCH((pbox->y1 << 16) | pbox->x1); +	 OUT_BATCH((pbox->y2 << 16) | pbox->x2); -      UNLOCK_HARDWARE(intel); -   } +	 OUT_RELOC(frontRegion->buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, +		   DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, 0); +	 OUT_BATCH((pbox->y1 << 16) | pbox->x1); +	 OUT_BATCH(BR13 & 0xffff); +	 OUT_RELOC(backRegion->buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, +		   DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, 0); -   if (!rect) { -      intel->swap_count++; -      (*dri_interface->getUST) (&ust); -      if (missed_target) { -         intel->swap_missed_count++; -         intel->swap_missed_ust = ust - intel->swap_ust; +	 ADVANCE_BATCH();        } -      intel->swap_ust = ust; +      if (intel->first_swap_fence) +	 driFenceUnReference(intel->first_swap_fence); +      intel->first_swap_fence = intel_batchbuffer_flush(intel->batch); +      driFenceReference(intel->first_swap_fence);     } + +   UNLOCK_HARDWARE(intel);  } @@ -406,6 +335,7 @@ void  intelClearWithBlit(GLcontext * ctx, GLbitfield mask)  {     struct intel_context *intel = intel_context(ctx); +   struct gl_framebuffer *fb = ctx->DrawBuffer;     GLuint clear_depth;     GLbitfield skipBuffers = 0;     BATCH_LOCALS; @@ -417,7 +347,7 @@ intelClearWithBlit(GLcontext * ctx, GLbitfield mask)      */     clear_depth = 0;     if (mask & BUFFER_BIT_DEPTH) { -      clear_depth = (GLuint) (ctx->DrawBuffer->_DepthMax * ctx->Depth.Clear); +      clear_depth = (GLuint) (fb->_DepthMax * ctx->Depth.Clear);     }     if (mask & BUFFER_BIT_STENCIL) {        clear_depth |= (ctx->Stencil.Clear & 0xff) << 24; @@ -440,12 +370,12 @@ intelClearWithBlit(GLcontext * ctx, GLbitfield mask)        int i;        /* Get clear bounds after locking */ -      cx = ctx->DrawBuffer->_Xmin; -      cy = ctx->DrawBuffer->_Ymin; -      cw = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; -      ch = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; +      cx = fb->_Xmin; +      cy = fb->_Ymin; +      cw = fb->_Xmax - cx; +      ch = fb->_Ymax - cy; -      if (intel->ctx.DrawBuffer->Name == 0) { +      if (fb->Name == 0) {           /* clearing a window */           /* flip top to bottom */ @@ -453,16 +383,6 @@ intelClearWithBlit(GLcontext * ctx, GLbitfield mask)           clear.y1 = intel->driDrawable->y + intel->driDrawable->h - cy - ch;           clear.x2 = clear.x1 + cw;           clear.y2 = clear.y1 + ch; - -         /* adjust for page flipping */ -         if (intel->sarea->pf_current_page == 1) { -            const GLuint tmp = mask; -            mask &= ~(BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT); -            if (tmp & BUFFER_BIT_FRONT_LEFT) -               mask |= BUFFER_BIT_BACK_LEFT; -            if (tmp & BUFFER_BIT_BACK_LEFT) -               mask |= BUFFER_BIT_FRONT_LEFT; -         }        }        else {           /* clearing FBO */ @@ -480,8 +400,7 @@ intelClearWithBlit(GLcontext * ctx, GLbitfield mask)           drm_clip_rect_t b;           GLuint buf;           GLuint clearMask = mask;      /* use copy, since we modify it below */ -         GLboolean all = (cw == ctx->DrawBuffer->Width && -                          ch == ctx->DrawBuffer->Height); +         GLboolean all = (cw == fb->Width && ch == fb->Height);           if (!all) {              intel_intersect_cliprects(&b, &clear, box); @@ -499,11 +418,10 @@ intelClearWithBlit(GLcontext * ctx, GLbitfield mask)              const GLbitfield bufBit = 1 << buf;              if ((clearMask & bufBit) && !(bufBit & skipBuffers)) {                 /* OK, clear this renderbuffer */ -               const struct intel_renderbuffer *irb -                  = intel_renderbuffer(ctx->DrawBuffer-> -                                       Attachment[buf].Renderbuffer); +               struct intel_region *irb_region = +		  intel_get_rb_region(fb, buf);                 struct _DriBufferObject *write_buffer = -                  intel_region_buffer(intel->intelScreen, irb->region, +                  intel_region_buffer(intel->intelScreen, irb_region,                                        all ? INTEL_WRITE_FULL :                                        INTEL_WRITE_PART); @@ -511,16 +429,15 @@ intelClearWithBlit(GLcontext * ctx, GLbitfield mask)                 GLint pitch, cpp;                 GLuint BR13, CMD; -               ASSERT(irb); -               ASSERT(irb->region); +               ASSERT(irb_region); -               pitch = irb->region->pitch; -               cpp = irb->region->cpp; +               pitch = irb_region->pitch; +               cpp = irb_region->cpp;                 DBG("%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n",                     __FUNCTION__, -                   irb->region->buffer, (pitch * cpp), -                   irb->region->draw_offset, +                   irb_region->buffer, (pitch * cpp), +                   irb_region->draw_offset,                     b.x1, b.y1, b.x2 - b.x1, b.y2 - b.y1); @@ -558,6 +475,8 @@ intelClearWithBlit(GLcontext * ctx, GLbitfield mask)                    _mesa_debug(ctx, "hardware blit clear buf %d rb id %d\n",                    buf, irb->Base.Name);                  */ +	       intel_wait_flips(intel, INTEL_BATCH_NO_CLIPRECTS); +                 BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS);                 OUT_BATCH(CMD);                 OUT_BATCH(BR13); @@ -565,7 +484,7 @@ intelClearWithBlit(GLcontext * ctx, GLbitfield mask)                 OUT_BATCH((b.y2 << 16) | b.x2);                 OUT_RELOC(write_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,                           DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, -                         irb->region->draw_offset); +                         irb_region->draw_offset);                 OUT_BATCH(clearVal);                 ADVANCE_BATCH();                 clearMask &= ~bufBit;    /* turn off bit, for faster loop exit */ diff --git a/src/mesa/drivers/dri/i915tex/intel_buffers.c b/src/mesa/drivers/dri/i915tex/intel_buffers.c index 1ded0b5417..164395719c 100644 --- a/src/mesa/drivers/dri/i915tex/intel_buffers.c +++ b/src/mesa/drivers/dri/i915tex/intel_buffers.c @@ -34,6 +34,7 @@  #include "intel_tris.h"  #include "intel_regions.h"  #include "intel_batchbuffer.h" +#include "intel_reg.h"  #include "context.h"  #include "utils.h"  #include "drirenderbuffer.h" @@ -155,11 +156,14 @@ static void  intelSetBackClipRects(struct intel_context *intel)  {     __DRIdrawablePrivate *dPriv = intel->driDrawable; +   struct intel_framebuffer *intel_fb;     if (!dPriv)        return; -   if (intel->sarea->pf_enabled == 0 && dPriv->numBackClipRects == 0) { +   intel_fb = dPriv->driverPrivate; + +   if (intel_fb->pf_active || dPriv->numBackClipRects == 0) {        /* use the front clip rects */        intel->numClipRects = dPriv->numClipRects;        intel->pClipRects = dPriv->pClipRects; @@ -185,7 +189,7 @@ intelWindowMoved(struct intel_context *intel)  {     GLcontext *ctx = &intel->ctx;     __DRIdrawablePrivate *dPriv = intel->driDrawable; -   GLframebuffer *drawFb = (GLframebuffer *) dPriv->driverPrivate; +   struct intel_framebuffer *intel_fb = dPriv->driverPrivate;     if (!intel->ctx.DrawBuffer) {        /* when would this happen? -BP */ @@ -197,7 +201,7 @@ intelWindowMoved(struct intel_context *intel)     }     else {        /* drawing to a window */ -      switch (drawFb->_ColorDrawBufferMask[0]) { +      switch (intel_fb->Base._ColorDrawBufferMask[0]) {        case BUFFER_BIT_FRONT_LEFT:           intelSetFrontClipRects(intel);           break; @@ -210,10 +214,6 @@ intelWindowMoved(struct intel_context *intel)        }     } -   /* Update Mesa's notion of window size */ -   driUpdateFramebufferSize(ctx, dPriv); -   drawFb->Initialized = GL_TRUE; /* XXX remove someday */ -     if (intel->intelScreen->driScrnPriv->ddxMinor >= 7) {        drmI830Sarea *sarea = intel->sarea;        drm_clip_rect_t drw_rect = { .x1 = dPriv->x, .x2 = dPriv->x + dPriv->w, @@ -226,22 +226,110 @@ intelWindowMoved(struct intel_context *intel)  				     .y2 = sarea->pipeB_y + sarea->pipeB_h };        GLint areaA = driIntersectArea( drw_rect, pipeA_rect );        GLint areaB = driIntersectArea( drw_rect, pipeB_rect ); -      GLuint flags = intel->vblank_flags; +      GLuint flags = intel_fb->vblank_flags; +      GLboolean pf_active; +      GLint pf_pipes; + +      /* Update page flipping info +       */ +      pf_pipes = 0; + +      if (areaA > 0) +	 pf_pipes |= 1; + +      if (areaB > 0) +	 pf_pipes |= 2; + +      intel_fb->pf_current_page = (intel->sarea->pf_current_page >> +				   (intel_fb->pf_pipes & 0x2)) & 0x3; + +      intel_fb->pf_num_pages = intel->intelScreen->third.handle ? 3 : 2; + +      pf_active = pf_pipes && (pf_pipes & intel->sarea->pf_active) == pf_pipes; + +      if (INTEL_DEBUG & DEBUG_LOCK) +	 if (pf_active != intel_fb->pf_active) +	    _mesa_printf("%s - Page flipping %sactive\n", __progname, +			 pf_active ? "" : "in"); + +      if (pf_active) { +	 /* Sync pages between pipes if we're flipping on both at the same time */ +	 if (pf_pipes == 0x3 &&	pf_pipes != intel_fb->pf_pipes && +	     (intel->sarea->pf_current_page & 0x3) != +	     (((intel->sarea->pf_current_page) >> 2) & 0x3)) { +	    drm_i915_flip_t flip; + +	    if (intel_fb->pf_current_page == +		(intel->sarea->pf_current_page & 0x3)) { +	       /* XXX: This is ugly, but emitting two flips 'in a row' can cause +		* lockups for unknown reasons. +		*/ +               intel->sarea->pf_current_page = +		  intel->sarea->pf_current_page & 0x3; +	       intel->sarea->pf_current_page |= +		  ((intel_fb->pf_current_page + intel_fb->pf_num_pages - 1) % +		   intel_fb->pf_num_pages) << 2; +	       flip.pipes = 0x2; +	    } else { +               intel->sarea->pf_current_page = +		  intel->sarea->pf_current_page & (0x3 << 2); +	       intel->sarea->pf_current_page |= +		  (intel_fb->pf_current_page + intel_fb->pf_num_pages - 1) % +		  intel_fb->pf_num_pages; + +	       flip.pipes = 0x1; +	    } + +	    drmCommandWrite(intel->driFd, DRM_I915_FLIP, &flip, sizeof(flip)); +	 } + +	 intel_fb->pf_pipes = pf_pipes; +      } + +      intel_fb->pf_active = pf_active; +      intel_flip_renderbuffers(intel_fb); +      intel_draw_buffer(&intel->ctx, intel->ctx.DrawBuffer); + +      /* Update vblank info +       */        if (areaB > areaA || (areaA == areaB && areaB > 0)) { -	 flags = intel->vblank_flags | VBLANK_FLAG_SECONDARY; +	 flags = intel_fb->vblank_flags | VBLANK_FLAG_SECONDARY;        } else { -	 flags = intel->vblank_flags & ~VBLANK_FLAG_SECONDARY; +	 flags = intel_fb->vblank_flags & ~VBLANK_FLAG_SECONDARY;        } -      if (flags != intel->vblank_flags) { -	 intel->vblank_flags = flags; -	 driGetCurrentVBlank(dPriv, intel->vblank_flags, &intel->vbl_seq); +      if (flags != intel_fb->vblank_flags) { +	 drmVBlank vbl; +	 int i; + +	 vbl.request.type = DRM_VBLANK_ABSOLUTE; + +	 if ( intel_fb->vblank_flags & VBLANK_FLAG_SECONDARY ) { +	    vbl.request.type |= DRM_VBLANK_SECONDARY; +	 } + +	 for (i = 0; i < intel_fb->pf_num_pages; i++) { +	    vbl.request.sequence = intel_fb->color_rb[i]->vbl_pending; +	    drmWaitVBlank(intel->driFd, &vbl); +	 } + +	 intel_fb->vblank_flags = flags; +	 driGetCurrentVBlank(dPriv, intel_fb->vblank_flags, &intel_fb->vbl_seq); +	 intel_fb->vbl_waited = intel_fb->vbl_seq; + +	 for (i = 0; i < intel_fb->pf_num_pages; i++) { +	    intel_fb->color_rb[i]->vbl_pending = intel_fb->vbl_waited; +	 }        }     } else { -      intel->vblank_flags &= ~VBLANK_FLAG_SECONDARY; +      intel_fb->vblank_flags &= ~VBLANK_FLAG_SECONDARY;     } +   /* Update Mesa's notion of window size */ +   driUpdateFramebufferSize(ctx, dPriv); +   intel_fb->Base.Initialized = GL_TRUE; /* XXX remove someday */ +     /* Update hardware scissor */     ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,                         ctx->Scissor.Width, ctx->Scissor.Height); @@ -259,6 +347,7 @@ static void  intelClearWithTris(struct intel_context *intel, GLbitfield mask)  {     GLcontext *ctx = &intel->ctx; +   struct gl_framebuffer *fb = ctx->DrawBuffer;     drm_clip_rect_t clear;     if (INTEL_DEBUG & DEBUG_BLIT) @@ -274,10 +363,10 @@ intelClearWithTris(struct intel_context *intel, GLbitfield mask)        intel->vtbl.install_meta_state(intel);        /* Get clear bounds after locking */ -      cx = ctx->DrawBuffer->_Xmin; -      cy = ctx->DrawBuffer->_Ymin; -      ch = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; -      cw = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; +      cx = fb->_Xmin; +      cy = fb->_Ymin; +      ch = fb->_Ymax - cx; +      cw = fb->_Xmax - cy;        /* note: regardless of 'all', cx, cy, cw, ch are now correct */        clear.x1 = cx; @@ -291,9 +380,9 @@ intelClearWithTris(struct intel_context *intel, GLbitfield mask)        if (mask &            (BUFFER_BIT_BACK_LEFT | BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH)) {           struct intel_region *backRegion = -            intel_get_rb_region(ctx->DrawBuffer, BUFFER_BACK_LEFT); +            intel_get_rb_region(fb, BUFFER_BACK_LEFT);           struct intel_region *depthRegion = -            intel_get_rb_region(ctx->DrawBuffer, BUFFER_DEPTH); +            intel_get_rb_region(fb, BUFFER_DEPTH);           const GLuint clearColor = (backRegion && backRegion->cpp == 4)              ? intel->ClearColor8888 : intel->ClearColor565; @@ -330,8 +419,7 @@ intelClearWithTris(struct intel_context *intel, GLbitfield mask)           const GLuint bufBit = 1 << buf;           if (mask & bufBit) {              struct intel_renderbuffer *irbColor = -               intel_renderbuffer(ctx->DrawBuffer-> -                                  Attachment[buf].Renderbuffer); +               intel_renderbuffer(fb->Attachment[buf].Renderbuffer);              GLuint color = (irbColor->region->cpp == 4)                 ? intel->ClearColor8888 : intel->ClearColor565; @@ -372,6 +460,7 @@ intelRotateWindow(struct intel_context *intel,  {     intelScreenPrivate *screen = intel->intelScreen;     drm_clip_rect_t fullRect; +   struct intel_framebuffer *intel_fb;     struct intel_region *src;     const drm_clip_rect_t *clipRects;     int numClipRects; @@ -421,16 +510,18 @@ intelRotateWindow(struct intel_context *intel,     intel->vtbl.meta_draw_region(intel, screen->rotated_region, NULL);    /* ? */ -   if (srcBuf == BUFFER_BIT_FRONT_LEFT) { -      src = intel->intelScreen->front_region; -      clipRects = dPriv->pClipRects; -      numClipRects = dPriv->numClipRects; -   } -   else { -      src = intel->intelScreen->back_region; +   intel_fb = dPriv->driverPrivate; + +   if ((srcBuf == BUFFER_BIT_BACK_LEFT && !intel_fb->pf_active)) { +      src = intel_get_rb_region(&intel_fb->Base, BUFFER_BACK_LEFT);        clipRects = dPriv->pBackClipRects;        numClipRects = dPriv->numBackClipRects;     } +   else { +      src = intel_get_rb_region(&intel_fb->Base, BUFFER_FRONT_LEFT); +      clipRects = dPriv->pClipRects; +      numClipRects = dPriv->numClipRects; +   }     if (src->cpp == 4) {        format = GL_BGRA; @@ -516,6 +607,7 @@ intelClear(GLcontext *ctx, GLbitfield mask)     GLbitfield tri_mask = 0;     GLbitfield blit_mask = 0;     GLbitfield swrast_mask = 0; +   struct gl_framebuffer *fb = ctx->DrawBuffer;     GLuint i;     if (0) @@ -535,7 +627,7 @@ intelClear(GLcontext *ctx, GLbitfield mask)     /* HW stencil */     if (mask & BUFFER_BIT_STENCIL) {        const struct intel_region *stencilRegion -         = intel_get_rb_region(ctx->DrawBuffer, BUFFER_STENCIL); +         = intel_get_rb_region(fb, BUFFER_STENCIL);        if (stencilRegion) {           /* have hw stencil */           if ((ctx->Stencil.WriteMask[0] & 0xff) != 0xff) { @@ -564,7 +656,7 @@ intelClear(GLcontext *ctx, GLbitfield mask)     for (i = 0; i < BUFFER_COUNT; i++) {        GLuint bufBit = 1 << i;        if ((blit_mask | tri_mask) & bufBit) { -         if (!ctx->DrawBuffer->Attachment[i].Renderbuffer->ClassID) { +         if (!fb->Attachment[i].Renderbuffer->ClassID) {              blit_mask &= ~bufBit;              tri_mask &= ~bufBit;              swrast_mask |= bufBit; @@ -586,15 +678,43 @@ intelClear(GLcontext *ctx, GLbitfield mask)  } +/* Emit wait for pending flips */ +void +intel_wait_flips(struct intel_context *intel, GLuint batch_flags) +{ +   struct intel_framebuffer *intel_fb = +      (struct intel_framebuffer *) intel->ctx.DrawBuffer; +   struct intel_renderbuffer *intel_rb = +      intel_get_renderbuffer(&intel_fb->Base, +			     intel_fb->Base._ColorDrawBufferMask[0] == +			     BUFFER_BIT_FRONT_LEFT ? BUFFER_FRONT_LEFT : +			     BUFFER_BACK_LEFT); + +   if (intel_fb->Base.Name == 0 && intel_rb->pf_pending == intel_fb->pf_seq) { +      GLint pf_pipes = intel_fb->pf_pipes; +      BATCH_LOCALS; + +      /* Wait for pending flips to take effect */ +      BEGIN_BATCH(2, batch_flags); +      OUT_BATCH(pf_pipes & 0x1 ? (MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP) +		: 0); +      OUT_BATCH(pf_pipes & 0x2 ? (MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_B_FLIP) +		: 0); +      ADVANCE_BATCH(); + +      intel_rb->pf_pending--; +   } +} +  /* Flip the front & back buffers   */ -static void +static GLboolean  intelPageFlip(const __DRIdrawablePrivate * dPriv)  { -#if 0     struct intel_context *intel; -   int tmp, ret; +   int ret; +   struct intel_framebuffer *intel_fb = dPriv->driverPrivate;     if (INTEL_DEBUG & DEBUG_IOCTL)        fprintf(stderr, "%s\n", __FUNCTION__); @@ -605,28 +725,45 @@ intelPageFlip(const __DRIdrawablePrivate * dPriv)     intel = (struct intel_context *) dPriv->driContextPriv->driverPrivate; +   if (intel->intelScreen->drmMinor < 9) +      return GL_FALSE; +     intelFlush(&intel->ctx); + +   ret = 0; +     LOCK_HARDWARE(intel); -   if (dPriv->pClipRects) { -      *(drm_clip_rect_t *) intel->sarea->boxes = dPriv->pClipRects[0]; -      intel->sarea->nbox = 1; -   } +   if (dPriv->numClipRects && intel_fb->pf_active) { +      drm_i915_flip_t flip; -   ret = drmCommandNone(intel->driFd, DRM_I830_FLIP); -   if (ret) { -      fprintf(stderr, "%s: %d\n", __FUNCTION__, ret); -      UNLOCK_HARDWARE(intel); -      exit(1); +      flip.pipes = intel_fb->pf_pipes; + +      ret = drmCommandWrite(intel->driFd, DRM_I915_FLIP, &flip, sizeof(flip));     } -   tmp = intel->sarea->last_enqueue; -   intelRefillBatchLocked(intel);     UNLOCK_HARDWARE(intel); +   if (ret || !intel_fb->pf_active) +      return GL_FALSE; -   intelSetDrawBuffer(&intel->ctx, intel->ctx.Color.DriverDrawBuffer); -#endif +   if (!dPriv->numClipRects) { +      usleep(10000);	/* throttle invisible client 10ms */ +   } + +   intel_fb->pf_current_page = (intel->sarea->pf_current_page >> +				(intel_fb->pf_pipes & 0x2)) & 0x3; + +   if (dPriv->numClipRects != 0) { +      intel_get_renderbuffer(&intel_fb->Base, BUFFER_FRONT_LEFT)->pf_pending = +      intel_get_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT)->pf_pending = +	 ++intel_fb->pf_seq; +   } + +   intel_flip_renderbuffers(intel_fb); +   intel_draw_buffer(&intel->ctx, &intel_fb->Base); + +   return GL_TRUE;  }  #if 0 @@ -641,7 +778,7 @@ intelSwapBuffers(__DRIdrawablePrivate * dPriv)           if (ctx && ctx->DrawBuffer == fb) {              _mesa_notifySwapBuffers(ctx);       /* flush pending rendering */           } -         if (0 /*intel->doPageFlip */ ) {       /* doPageFlip is never set !!! */ +         if (intel->doPageFlip) {              intelPageFlip(dPriv);           }           else { @@ -657,6 +794,83 @@ intelSwapBuffers(__DRIdrawablePrivate * dPriv)  #else  /* Trunk version:   */ + +static GLboolean +intelScheduleSwap(const __DRIdrawablePrivate * dPriv, GLboolean *missed_target) +{ +   struct intel_framebuffer *intel_fb = dPriv->driverPrivate; +   unsigned int interval = driGetVBlankInterval(dPriv, intel_fb->vblank_flags); +   struct intel_context *intel = +      intelScreenContext(dPriv->driScreenPriv->private); +   const intelScreenPrivate *intelScreen = intel->intelScreen; +   unsigned int target; +   drm_i915_vblank_swap_t swap; +   GLboolean ret; + +   if ((intel_fb->vblank_flags & VBLANK_FLAG_NO_IRQ) || +       intelScreen->current_rotation != 0 || +       intelScreen->drmMinor < (intel_fb->pf_active ? 9 : 6)) +      return GL_FALSE; + +   swap.seqtype = DRM_VBLANK_ABSOLUTE; + +   if (intel_fb->vblank_flags & VBLANK_FLAG_SYNC) { +      swap.seqtype |= DRM_VBLANK_NEXTONMISS; +   } else if (interval == 0) { +      return GL_FALSE; +   } + +   swap.drawable = dPriv->hHWDrawable; +   target = swap.sequence = intel_fb->vbl_seq + interval; + +   if ( intel_fb->vblank_flags & VBLANK_FLAG_SECONDARY ) { +      swap.seqtype |= DRM_VBLANK_SECONDARY; +   } + +   LOCK_HARDWARE(intel); + +   intel_batchbuffer_flush(intel->batch); + +   if ( intel_fb->pf_active ) { +      swap.seqtype |= DRM_VBLANK_FLIP; + +      intel_fb->pf_current_page = (((intel->sarea->pf_current_page >> +				     (intel_fb->pf_pipes & 0x2)) & 0x3) + 1) % +				  intel_fb->pf_num_pages; +   } + +   if (!drmCommandWriteRead(intel->driFd, DRM_I915_VBLANK_SWAP, &swap, +			    sizeof(swap))) { +      intel_fb->vbl_seq = swap.sequence; +      swap.sequence -= target; +      *missed_target = swap.sequence > 0 && swap.sequence <= (1 << 23); + +      intel_get_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT)->vbl_pending = +	 intel_get_renderbuffer(&intel_fb->Base, +				BUFFER_FRONT_LEFT)->vbl_pending = +	 intel_fb->vbl_seq; + +      if (swap.seqtype & DRM_VBLANK_FLIP) { +	 intel_flip_renderbuffers(intel_fb); +	 intel_draw_buffer(&intel->ctx, intel->ctx.DrawBuffer); +      } + +      ret = GL_TRUE; +   } else { +      if (swap.seqtype & DRM_VBLANK_FLIP) { +	 intel_fb->pf_current_page = ((intel->sarea->pf_current_page >> +					(intel_fb->pf_pipes & 0x2)) & 0x3) % +				     intel_fb->pf_num_pages; +      } + +      ret = GL_FALSE; +   } + +   UNLOCK_HARDWARE(intel); + +   return ret; +} +    void  intelSwapBuffers(__DRIdrawablePrivate * dPriv)  { @@ -671,16 +885,34 @@ intelSwapBuffers(__DRIdrawablePrivate * dPriv)        if (ctx->Visual.doubleBufferMode) {           intelScreenPrivate *screen = intel->intelScreen; -         _mesa_notifySwapBuffers(ctx);  /* flush pending rendering comands */ -         if (0 /*intel->doPageFlip */ ) {       /* doPageFlip is never set !!! */ -            intelPageFlip(dPriv); -         } -         else { -            intelCopyBuffer(dPriv, NULL); -         } -         if (screen->current_rotation != 0) { -            intelRotateWindow(intel, dPriv, BUFFER_BIT_FRONT_LEFT); -         } +	 GLboolean missed_target; +	 struct intel_framebuffer *intel_fb = dPriv->driverPrivate; +	 int64_t ust; +          +	 _mesa_notifySwapBuffers(ctx);  /* flush pending rendering comands */ + +         if (screen->current_rotation != 0 || +	     !intelScheduleSwap(dPriv, &missed_target)) { +	    driWaitForVBlank(dPriv, &intel_fb->vbl_seq, intel_fb->vblank_flags, +			     &missed_target); + +	    if (screen->current_rotation != 0 || !intelPageFlip(dPriv)) { +	       intelCopyBuffer(dPriv, NULL); +	    } + +	    if (screen->current_rotation != 0) { +	       intelRotateWindow(intel, dPriv, BUFFER_BIT_FRONT_LEFT); +	    } +	 } + +	 intel_fb->swap_count++; +	 (*dri_interface->getUST) (&ust); +	 if (missed_target) { +	    intel_fb->swap_missed_count++; +	    intel_fb->swap_missed_ust = ust - intel_fb->swap_ust; +	 } + +	 intel_fb->swap_ust = ust;        }     }     else { @@ -788,10 +1020,6 @@ intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb)      */     if (fb->Name == 0) {        /* drawing to window system buffer */ -      if (intel->sarea->pf_current_page == 1) { -         /* page flipped back/front */ -         front ^= 1; -      }        if (front) {           intelSetFrontClipRects(intel);           colorRegion = intel_get_rb_region(fb, BUFFER_FRONT_LEFT); diff --git a/src/mesa/drivers/dri/i915tex/intel_buffers.h b/src/mesa/drivers/dri/i915tex/intel_buffers.h index 0faf055347..3b686cb5c1 100644 --- a/src/mesa/drivers/dri/i915tex/intel_buffers.h +++ b/src/mesa/drivers/dri/i915tex/intel_buffers.h @@ -30,6 +30,7 @@  struct intel_context; +struct intel_framebuffer;  extern GLboolean @@ -41,6 +42,8 @@ extern struct intel_region *intel_readbuf_region(struct intel_context *intel);  extern struct intel_region *intel_drawbuf_region(struct intel_context *intel); +extern void intel_wait_flips(struct intel_context *intel, GLuint batch_flags); +  extern void intelSwapBuffers(__DRIdrawablePrivate * dPriv);  extern void intelWindowMoved(struct intel_context *intel); diff --git a/src/mesa/drivers/dri/i915tex/intel_context.c b/src/mesa/drivers/dri/i915tex/intel_context.c index a5ce08b170..5c2cdf0c7d 100644 --- a/src/mesa/drivers/dri/i915tex/intel_context.c +++ b/src/mesa/drivers/dri/i915tex/intel_context.c @@ -59,6 +59,7 @@  #include "intel_buffer_objects.h"  #include "intel_fbo.h" +#include "drirenderbuffer.h"  #include "vblank.h"  #include "utils.h"  #include "xmlpool.h"            /* for symbolic values of enum-type options */ @@ -442,10 +443,6 @@ intelInitContext(struct intel_context *intel,     intel->do_usleeps = (fthrottle_mode == DRI_CONF_FTHROTTLE_USLEEPS); -   intel->vblank_flags = (intel->intelScreen->irq_active != 0) -      ? driGetDefaultVBlankFlags(&intel->optionCache) : VBLANK_FLAG_NO_IRQ; - -   (*dri_interface->getUST) (&intel->swap_ust);     _math_matrix_ctr(&intel->ViewportMatrix);     /* Disable imaging extension until convolution is working in @@ -550,27 +547,30 @@ intelMakeCurrent(__DRIcontextPrivate * driContextPriv,     if (driContextPriv) {        struct intel_context *intel =           (struct intel_context *) driContextPriv->driverPrivate; -      GLframebuffer *drawFb = (GLframebuffer *) driDrawPriv->driverPrivate; +      struct intel_framebuffer *intel_fb = +	 (struct intel_framebuffer *) driDrawPriv->driverPrivate;        GLframebuffer *readFb = (GLframebuffer *) driReadPriv->driverPrivate;        /* XXX FBO temporary fix-ups! */        /* if the renderbuffers don't have regions, init them from the context */        { -         struct intel_renderbuffer *irbFront -            = intel_get_renderbuffer(drawFb, BUFFER_FRONT_LEFT); -         struct intel_renderbuffer *irbBack -            = intel_get_renderbuffer(drawFb, BUFFER_BACK_LEFT);           struct intel_renderbuffer *irbDepth -            = intel_get_renderbuffer(drawFb, BUFFER_DEPTH); +            = intel_get_renderbuffer(&intel_fb->Base, BUFFER_DEPTH);           struct intel_renderbuffer *irbStencil -            = intel_get_renderbuffer(drawFb, BUFFER_STENCIL); +            = intel_get_renderbuffer(&intel_fb->Base, BUFFER_STENCIL); -         if (irbFront && !irbFront->region) { -            intel_region_reference(&irbFront->region, intel->intelScreen->front_region); +         if (intel_fb->color_rb[0] && !intel_fb->color_rb[0]->region) { +            intel_region_reference(&intel_fb->color_rb[0]->region, +				   intel->intelScreen->front_region); +         } +         if (intel_fb->color_rb[1] && !intel_fb->color_rb[1]->region) { +            intel_region_reference(&intel_fb->color_rb[1]->region, +				   intel->intelScreen->back_region);           } -         if (irbBack && !irbBack->region) { -            intel_region_reference(&irbBack->region, intel->intelScreen->back_region); +         if (intel_fb->color_rb[2] && !intel_fb->color_rb[2]->region) { +            intel_region_reference(&intel_fb->color_rb[2]->region, +				   intel->intelScreen->third_region);           }           if (irbDepth && !irbDepth->region) {              intel_region_reference(&irbDepth->region, intel->intelScreen->depth_region); @@ -580,29 +580,34 @@ intelMakeCurrent(__DRIcontextPrivate * driContextPriv,           }        } -      /* set initial GLframebuffer size to match window, if needed */ -      if (drawFb->Width == 0 && driDrawPriv->w) { -         _mesa_resize_framebuffer(&intel->ctx, drawFb, +      /* set GLframebuffer size to match window, if needed */ +      if (intel_fb->Base.Width != driDrawPriv->w) { +         _mesa_resize_framebuffer(&intel->ctx, &intel_fb->Base,                                    driDrawPriv->w, driDrawPriv->h);        }          -      if (readFb->Width == 0 && driReadPriv->w) { +      if (readFb->Width != driReadPriv->w) {           _mesa_resize_framebuffer(&intel->ctx, readFb,                                    driReadPriv->w, driReadPriv->h);        }          -      _mesa_make_current(&intel->ctx, drawFb, readFb); +      _mesa_make_current(&intel->ctx, &intel_fb->Base, readFb);        /* The drawbuffer won't always be updated by _mesa_make_current:          */ -      if (intel->ctx.DrawBuffer == drawFb) { +      if (intel->ctx.DrawBuffer == &intel_fb->Base) {  	 if (intel->driDrawable != driDrawPriv) { -	    driDrawableInitVBlank(driDrawPriv, intel->vblank_flags, &intel->vbl_seq);	     +	    intel_fb->vblank_flags = (intel->intelScreen->irq_active != 0) +	       ? driGetDefaultVBlankFlags(&intel->optionCache) +	       : VBLANK_FLAG_NO_IRQ; +	    (*dri_interface->getUST) (&intel_fb->swap_ust); +	    driDrawableInitVBlank(driDrawPriv, intel_fb->vblank_flags, +				  &intel_fb->vbl_seq);  	    intel->driDrawable = driDrawPriv;  	    intelWindowMoved(intel);  	 } -	 intel_draw_buffer(&intel->ctx, drawFb); +	 intel_draw_buffer(&intel->ctx, &intel_fb->Base);        }     }     else { @@ -683,7 +688,6 @@ intelContendedLock(struct intel_context *intel, GLuint flags)        intel->current_rotation = sarea->rotation;     } -     /* Drawable changed?      */     if (dPriv && intel->lastStamp != dPriv->lastStamp) { @@ -693,24 +697,40 @@ intelContendedLock(struct intel_context *intel, GLuint flags)  } +  /* Lock the hardware and validate our state.     */  void LOCK_HARDWARE( struct intel_context *intel )  {      char __ret=0; - +    struct intel_framebuffer *intel_fb = NULL; +    struct intel_renderbuffer *intel_rb = NULL;      _glthread_LOCK_MUTEX(lockMutex);      assert(!intel->locked); -    if (intel->swap_scheduled) { +    if (intel->driDrawable) { +       intel_fb = intel->driDrawable->driverPrivate; + +       if (intel_fb) +	  intel_rb = +	     intel_get_renderbuffer(&intel_fb->Base, +				    intel_fb->Base._ColorDrawBufferMask[0] == +				    BUFFER_BIT_FRONT_LEFT ? BUFFER_FRONT_LEFT : +				    BUFFER_BACK_LEFT); +    } + +    if (intel_rb && (intel_fb->vbl_waited - intel_rb->vbl_pending) > (1<<23)) {  	drmVBlank vbl; +  	vbl.request.type = DRM_VBLANK_ABSOLUTE; -	if ( intel->vblank_flags & VBLANK_FLAG_SECONDARY ) { + +	if ( intel_fb->vblank_flags & VBLANK_FLAG_SECONDARY ) {  	    vbl.request.type |= DRM_VBLANK_SECONDARY;  	} -	vbl.request.sequence = intel->vbl_seq; + +	vbl.request.sequence = intel_rb->vbl_pending;  	drmWaitVBlank(intel->driFd, &vbl); -	intel->swap_scheduled = 0; +	intel_fb->vbl_waited = vbl.reply.sequence;      }      DRM_CAS(intel->driHwLock, intel->hHWContext, diff --git a/src/mesa/drivers/dri/i915tex/intel_context.h b/src/mesa/drivers/dri/i915tex/intel_context.h index 96b911501f..44c20af7f8 100644 --- a/src/mesa/drivers/dri/i915tex/intel_context.h +++ b/src/mesa/drivers/dri/i915tex/intel_context.h @@ -274,19 +274,6 @@ struct intel_context      */     driOptionCache optionCache; -   /* VBI -    */ -   GLuint vbl_seq; -   GLuint vblank_flags; - -   int64_t swap_ust; -   int64_t swap_missed_ust; - -   GLuint swap_count; -   GLuint swap_missed_count; - -   GLuint swap_scheduled; -    /* Rotation. Need to match that of the     * current screen.     */ @@ -294,7 +281,6 @@ struct intel_context    int width;    int height;    int current_rotation; -  };  /* These are functions now: diff --git a/src/mesa/drivers/dri/i915tex/intel_fbo.c b/src/mesa/drivers/dri/i915tex/intel_fbo.c index ab0e569bd9..8d43055382 100644 --- a/src/mesa/drivers/dri/i915tex/intel_fbo.c +++ b/src/mesa/drivers/dri/i915tex/intel_fbo.c @@ -75,11 +75,35 @@ intel_get_renderbuffer(struct gl_framebuffer *fb, GLuint attIndex)  } +void +intel_flip_renderbuffers(struct intel_framebuffer *intel_fb) +{ +   int current_page = intel_fb->pf_current_page; +   int next_page = (current_page + 1) % intel_fb->pf_num_pages; + +   if (intel_fb->color_rb[current_page] && +       intel_fb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer != +       &intel_fb->color_rb[current_page]->Base) { +      _mesa_remove_renderbuffer(&intel_fb->Base, BUFFER_FRONT_LEFT); +      _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_FRONT_LEFT, +			     &intel_fb->color_rb[current_page]->Base); +   } + +   if (intel_fb->color_rb[next_page] && +       intel_fb->Base.Attachment[BUFFER_BACK_LEFT].Renderbuffer != +       &intel_fb->color_rb[next_page]->Base) { +      _mesa_remove_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT); +      _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT, +			     &intel_fb->color_rb[next_page]->Base); +   } +} + +  struct intel_region *  intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex)  { -   struct intel_renderbuffer *irb -      = intel_renderbuffer(fb->Attachment[attIndex].Renderbuffer); +   struct intel_renderbuffer *irb = intel_get_renderbuffer(fb, attIndex); +     if (irb)        return irb->region;     else @@ -94,7 +118,9 @@ intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex)  static struct gl_framebuffer *  intel_new_framebuffer(GLcontext * ctx, GLuint name)  { -   /* there's no intel_framebuffer at this time, just use Mesa's class */ +   /* Only drawable state in intel_framebuffer at this time, just use Mesa's +    * class +    */     return _mesa_new_framebuffer(ctx, name);  } @@ -271,10 +297,24 @@ static GLboolean  intel_alloc_window_storage(GLcontext * ctx, struct gl_renderbuffer *rb,                             GLenum internalFormat, GLuint width, GLuint height)  { +   struct intel_context *intel = intel_context(ctx); +   struct intel_framebuffer *intel_fb; +     ASSERT(rb->Name == 0);     rb->Width = width;     rb->Height = height;     rb->_ActualFormat = internalFormat; + +   if (intel && intel->driDrawable && +       (intel_fb = intel->driDrawable->driverPrivate) && +       intel_fb->pf_num_pages == 3 && +       rb == &intel_fb->color_rb[intel_fb->pf_current_page]->Base && +       (rb = &intel_fb->color_rb[(intel_fb->pf_current_page + 2) % 3]->Base)) { +      rb->Width = width; +      rb->Height = height; +      rb->_ActualFormat = internalFormat; +   } +     return GL_TRUE;  } diff --git a/src/mesa/drivers/dri/i915tex/intel_fbo.h b/src/mesa/drivers/dri/i915tex/intel_fbo.h index 221f09b39a..963f5e706f 100644 --- a/src/mesa/drivers/dri/i915tex/intel_fbo.h +++ b/src/mesa/drivers/dri/i915tex/intel_fbo.h @@ -32,6 +32,35 @@  struct intel_context;  struct intel_region; +/** + * Intel framebuffer, derived from gl_framebuffer. + */ +struct intel_framebuffer +{ +   struct gl_framebuffer Base; + +   struct intel_renderbuffer *color_rb[3]; + +   /* Drawable page flipping state */ +   GLboolean pf_active; +   GLuint pf_seq; +   GLint pf_pipes; +   GLint pf_current_page; +   GLint pf_num_pages; + +   /* VBI +    */ +   GLuint vbl_seq; +   GLuint vblank_flags; +   GLuint vbl_waited; + +   int64_t swap_ust; +   int64_t swap_missed_ust; + +   GLuint swap_count; +   GLuint swap_missed_count; +}; +  /**   * Intel renderbuffer, derived from gl_renderbuffer. @@ -49,6 +78,10 @@ struct intel_renderbuffer     GLuint PairedDepth;   /**< only used if this is a depth renderbuffer */     GLuint PairedStencil; /**< only used if this is a stencil renderbuffer */ + +   GLuint pf_pending;  /**< sequence number of pending flip */ + +   GLuint vbl_pending;   /**< vblank sequence number of pending flip */  }; @@ -69,6 +102,8 @@ extern struct intel_renderbuffer *intel_get_renderbuffer(struct gl_framebuffer                                                           *fb,                                                           GLuint attIndex); +extern void intel_flip_renderbuffers(struct intel_framebuffer *intel_fb); +  /* XXX make inline or macro */  extern struct intel_region *intel_get_rb_region(struct gl_framebuffer *fb, diff --git a/src/mesa/drivers/dri/i915tex/intel_reg.h b/src/mesa/drivers/dri/i915tex/intel_reg.h index 1ec153266c..7828ba6ad3 100644 --- a/src/mesa/drivers/dri/i915tex/intel_reg.h +++ b/src/mesa/drivers/dri/i915tex/intel_reg.h @@ -81,4 +81,8 @@  #define XY_SRC_COPY_BLT_WRITE_ALPHA     (1<<21)  #define XY_SRC_COPY_BLT_WRITE_RGB       (1<<20) +#define MI_WAIT_FOR_EVENT               ((0x3<<23)) +#define MI_WAIT_FOR_PLANE_B_FLIP        (1<<6) +#define MI_WAIT_FOR_PLANE_A_FLIP        (1<<2) +  #endif diff --git a/src/mesa/drivers/dri/i915tex/intel_screen.c b/src/mesa/drivers/dri/i915tex/intel_screen.c index ac83254593..a6342046b5 100644 --- a/src/mesa/drivers/dri/i915tex/intel_screen.c +++ b/src/mesa/drivers/dri/i915tex/intel_screen.c @@ -98,6 +98,18 @@ intelMapScreenRegions(__DRIscreenPrivate * sPriv)        return GL_FALSE;     } +   if (intelScreen->third.handle) { +      if (0) +	 _mesa_printf("Third 0x%08x ", intelScreen->third.handle); +      if (drmMap(sPriv->fd, +		 intelScreen->third.handle, +		 intelScreen->third.size, +		 (drmAddress *) & intelScreen->third.map) != 0) { +	 intelUnmapScreenRegions(intelScreen); +	 return GL_FALSE; +      } +   } +     if (0)        _mesa_printf("Depth 0x%08x ", intelScreen->depth.handle);     if (drmMap(sPriv->fd, @@ -119,9 +131,9 @@ intelMapScreenRegions(__DRIscreenPrivate * sPriv)     }  #endif     if (0) -      printf("Mappings:  front: %p  back: %p  depth: %p  tex: %p\n", +      printf("Mappings:  front: %p  back: %p  third: %p  depth: %p  tex: %p\n",               intelScreen->front.map, -             intelScreen->back.map, +             intelScreen->back.map, intelScreen->third.map,               intelScreen->depth.map, intelScreen->tex.map);     return GL_TRUE;  } @@ -191,6 +203,18 @@ intel_recreate_static_regions(intelScreenPrivate *intelScreen)  			    intelScreen->back.pitch / intelScreen->cpp,  			    intelScreen->height); +   if (intelScreen->third.handle) { +      intelScreen->third_region = +	 intel_recreate_static(intelScreen, +			       intelScreen->third_region, +			       DRM_BO_FLAG_MEM_TT, +			       intelScreen->third.offset, +			       intelScreen->third.map, +			       intelScreen->cpp, +			       intelScreen->third.pitch / intelScreen->cpp, +			       intelScreen->height); +   } +     /* Still assuming front.cpp == depth.cpp      */     intelScreen->depth_region = @@ -240,6 +264,13 @@ intelUnmapScreenRegions(intelScreenPrivate * intelScreen)  #endif        intelScreen->back.map = NULL;     } +   if (intelScreen->third.map) { +#if REALLY_UNMAP +      if (drmUnmap(intelScreen->third.map, intelScreen->third.size) != 0) +         printf("drmUnmap third failed!\n"); +#endif +      intelScreen->third.map = NULL; +   }     if (intelScreen->depth.map) {  #if REALLY_UNMAP        drmUnmap(intelScreen->depth.map, intelScreen->depth.size); @@ -325,6 +356,13 @@ intelUpdateScreenFromSAREA(intelScreenPrivate * intelScreen,     intelScreen->back.handle = sarea->back_handle;     intelScreen->back.size = sarea->back_size; +   if (intelScreen->driScrnPriv->ddxMinor >= 8) { +      intelScreen->third.offset = sarea->third_offset; +      intelScreen->third.pitch = sarea->pitch * intelScreen->cpp; +      intelScreen->third.handle = sarea->third_handle; +      intelScreen->third.size = sarea->third_size; +   } +     intelScreen->depth.offset = sarea->depth_offset;     intelScreen->depth.pitch = sarea->pitch * intelScreen->cpp;     intelScreen->depth.handle = sarea->depth_handle; @@ -541,31 +579,49 @@ intelCreateBuffer(__DRIscreenPrivate * driScrnPriv,                               mesaVis->depthBits != 24);        GLenum rgbFormat = (mesaVis->redBits == 5 ? GL_RGB5 : GL_RGBA8); -      struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis); +      struct intel_framebuffer *intel_fb = CALLOC_STRUCT(intel_framebuffer); + +      if (!intel_fb) +	 return GL_FALSE; + +      _mesa_initialize_framebuffer(&intel_fb->Base, mesaVis);        /* setup the hardware-based renderbuffers */        { -         struct intel_renderbuffer *frontRb +         intel_fb->color_rb[0]              = intel_create_renderbuffer(rgbFormat,                                          screen->width, screen->height,                                          screen->front.offset,                                          screen->front.pitch,                                          screen->cpp,                                          screen->front.map); -         intel_set_span_functions(&frontRb->Base); -         _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base); +         intel_set_span_functions(&intel_fb->color_rb[0]->Base); +         _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_FRONT_LEFT, +				&intel_fb->color_rb[0]->Base);        }        if (mesaVis->doubleBufferMode) { -         struct intel_renderbuffer *backRb +         intel_fb->color_rb[1]              = intel_create_renderbuffer(rgbFormat,                                          screen->width, screen->height,                                          screen->back.offset,                                          screen->back.pitch,                                          screen->cpp,                                          screen->back.map); -         intel_set_span_functions(&backRb->Base); -         _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base); +         intel_set_span_functions(&intel_fb->color_rb[1]->Base); +         _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT, +				&intel_fb->color_rb[1]->Base); + +	 if (screen->third.handle) { +	    intel_fb->color_rb[2] +	       = intel_create_renderbuffer(rgbFormat, +					   screen->width, screen->height, +					   screen->third.offset, +					   screen->third.pitch, +					   screen->cpp, +					   screen->third.map); +	    intel_set_span_functions(&intel_fb->color_rb[2]->Base); +	 }        }        if (mesaVis->depthBits == 24 && mesaVis->stencilBits == 8) { @@ -579,8 +635,10 @@ intelCreateBuffer(__DRIscreenPrivate * driScrnPriv,                                          screen->depth.map);           intel_set_span_functions(&depthStencilRb->Base);           /* note: bind RB to two attachment points */ -         _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthStencilRb->Base); -         _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &depthStencilRb->Base); +         _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH, +				&depthStencilRb->Base); +         _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_STENCIL, +				&depthStencilRb->Base);        }        else if (mesaVis->depthBits == 16) {           /* just 16-bit depth buffer, no hw stencil */ @@ -592,17 +650,19 @@ intelCreateBuffer(__DRIscreenPrivate * driScrnPriv,                                          screen->cpp,    /* 2! */                                          screen->depth.map);           intel_set_span_functions(&depthRb->Base); -         _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base); +         _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH, &depthRb->Base);        }        /* now add any/all software-based renderbuffers we may need */ -      _mesa_add_soft_renderbuffers(fb, GL_FALSE,        /* never sw color */ -                                   GL_FALSE,    /* never sw depth */ -                                   swStencil, mesaVis->accumRedBits > 0, GL_FALSE,      /* never sw alpha */ -                                   GL_FALSE /* never sw aux */ ); -      driDrawPriv->driverPrivate = (void *) fb; +      _mesa_add_soft_renderbuffers(&intel_fb->Base, +                                   GL_FALSE, /* never sw color */ +                                   GL_FALSE, /* never sw depth */ +                                   swStencil, mesaVis->accumRedBits > 0, +                                   GL_FALSE, /* never sw alpha */ +                                   GL_FALSE  /* never sw aux */ ); +      driDrawPriv->driverPrivate = (void *) intel_fb; -      return (driDrawPriv->driverPrivate != NULL); +      return GL_TRUE;     }  } @@ -619,21 +679,20 @@ intelDestroyBuffer(__DRIdrawablePrivate * driDrawPriv)  static int  intelGetSwapInfo(__DRIdrawablePrivate * dPriv, __DRIswapInfo * sInfo)  { -   struct intel_context *intel; +   struct intel_framebuffer *intel_fb; -   if ((dPriv == NULL) || (dPriv->driContextPriv == NULL) -       || (dPriv->driContextPriv->driverPrivate == NULL) +   if ((dPriv == NULL) || (dPriv->driverPrivate == NULL)         || (sInfo == NULL)) {        return -1;     } -   intel = dPriv->driContextPriv->driverPrivate; -   sInfo->swap_count = intel->swap_count; -   sInfo->swap_ust = intel->swap_ust; -   sInfo->swap_missed_count = intel->swap_missed_count; +   intel_fb = dPriv->driverPrivate; +   sInfo->swap_count = intel_fb->swap_count; +   sInfo->swap_ust = intel_fb->swap_ust; +   sInfo->swap_missed_count = intel_fb->swap_missed_count;     sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0) -      ? driCalculateSwapUsage(dPriv, 0, intel->swap_missed_ust) +      ? driCalculateSwapUsage(dPriv, 0, intel_fb->swap_missed_ust)        : 0.0;     return 0; diff --git a/src/mesa/drivers/dri/i915tex/intel_screen.h b/src/mesa/drivers/dri/i915tex/intel_screen.h index 17698773f3..05e2f1f2ea 100644 --- a/src/mesa/drivers/dri/i915tex/intel_screen.h +++ b/src/mesa/drivers/dri/i915tex/intel_screen.h @@ -51,12 +51,14 @@ typedef struct  {     intelRegion front;     intelRegion back; +   intelRegion third;     intelRegion rotated;     intelRegion depth;     intelRegion tex;     struct intel_region *front_region;     struct intel_region *back_region; +   struct intel_region *third_region;     struct intel_region *depth_region;     struct intel_region *rotated_region; diff --git a/src/mesa/drivers/dri/i915tex/intel_tris.c b/src/mesa/drivers/dri/i915tex/intel_tris.c index 1ba49d8f6e..9ac8c32f60 100644 --- a/src/mesa/drivers/dri/i915tex/intel_tris.c +++ b/src/mesa/drivers/dri/i915tex/intel_tris.c @@ -102,6 +102,8 @@ intelStartInlinePrimitive(struct intel_context *intel,  /*    _mesa_printf("%s *", __progname); */ +   intel_wait_flips(intel, batch_flags); +     /* Emit a slot which will be filled with the inline primitive      * command later.      */ diff --git a/src/mesa/drivers/dri/i915tex/server/i830_common.h b/src/mesa/drivers/dri/i915tex/server/i830_common.h index 06f28ed19a..d4d58886ce 100644 --- a/src/mesa/drivers/dri/i915tex/server/i830_common.h +++ b/src/mesa/drivers/dri/i915tex/server/i830_common.h @@ -129,6 +129,12 @@ typedef struct {  	int pipeB_y;  	int pipeB_w;  	int pipeB_h; + +	/* Triple buffering */ +	drm_handle_t third_handle; +	int third_offset; +	int third_size; +	unsigned int third_tiled;  } drmI830Sarea;  /* Flags for perf_boxes  | 
