From e33a9d689415e00bded306699abdf93b96c0b9ad Mon Sep 17 00:00:00 2001 From: =?utf8?q?Michel=20D=C3=A4nzer?= Date: Tue, 20 Feb 2007 19:14:23 +0100 Subject: [PATCH] i915tex: Triple buffering support, only effective with page flipping so far. Pending flips are tracked per renderbuffer and the colour renderbuffer attachments of window framebuffer objects are rotated on flips to avoid stalling the pipeline for pending flips unnecessarily. --- src/mesa/drivers/dri/i915tex/intel_buffers.c | 47 +++++++++----- src/mesa/drivers/dri/i915tex/intel_context.c | 51 ++++++++------- src/mesa/drivers/dri/i915tex/intel_fbo.c | 49 ++++++++++---- src/mesa/drivers/dri/i915tex/intel_fbo.h | 9 ++- src/mesa/drivers/dri/i915tex/intel_screen.c | 65 ++++++++++++++++--- src/mesa/drivers/dri/i915tex/intel_screen.h | 2 + .../drivers/dri/i915tex/server/i830_common.h | 6 ++ 7 files changed, 166 insertions(+), 63 deletions(-) diff --git a/src/mesa/drivers/dri/i915tex/intel_buffers.c b/src/mesa/drivers/dri/i915tex/intel_buffers.c index ec2150d27bc..7db5ccfc265 100644 --- a/src/mesa/drivers/dri/i915tex/intel_buffers.c +++ b/src/mesa/drivers/dri/i915tex/intel_buffers.c @@ -214,10 +214,6 @@ intelWindowMoved(struct intel_context *intel) } } - /* Update Mesa's notion of window size */ - driUpdateFramebufferSize(ctx, dPriv); - intel_fb->Base.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, @@ -247,7 +243,9 @@ intelWindowMoved(struct intel_context *intel) intel_fb->pf_current_page = (intel->sarea->pf_current_page >> (intel_fb->pf_pipes & 0x2)) & 0x3; - pf_active = (pf_pipes & intel->sarea->pf_active) == pf_pipes; + 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) @@ -255,9 +253,13 @@ intelWindowMoved(struct intel_context *intel) pf_active ? "" : "in"); if (pf_active) { - if (pf_pipes != intel_fb->pf_pipes && intel_fb->pf_pipes == 0x3 && - (intel->sarea->pf_current_page & 0x3) != - ((intel->sarea->pf_current_page) >> 2 & 0x3)) { + int i; + + /* Sync pages between pipes if we're flipping on both at the same time */ + for (i = 0; i < 2 && pf_pipes != intel_fb->pf_pipes && + intel_fb->pf_pipes == 0x3 && + (intel->sarea->pf_current_page & 0x3) != + ((intel->sarea->pf_current_page) >> 2 & 0x3); i++) { drm_i915_flip_t flip; flip.pipes = (intel_fb->pf_current_page == @@ -270,7 +272,7 @@ intelWindowMoved(struct intel_context *intel) } intel_fb->pf_active = pf_active; - driFlipRenderbuffers(intel->ctx.WinSysDrawBuffer, intel_fb->pf_current_page); + intel_flip_renderbuffers(intel_fb); intel_draw_buffer(&intel->ctx, intel->ctx.DrawBuffer); /* Update vblank info @@ -289,6 +291,10 @@ intelWindowMoved(struct intel_context *intel) intel->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); @@ -472,12 +478,12 @@ intelRotateWindow(struct intel_context *intel, intel_fb = dPriv->driverPrivate; if ((srcBuf == BUFFER_BIT_BACK_LEFT && !intel_fb->pf_active)) { - src = intel->intelScreen->back_region; + src = intel_get_rb_region(&intel_fb->Base, BUFFER_BACK_LEFT); clipRects = dPriv->pBackClipRects; numClipRects = dPriv->numBackClipRects; } else { - src = intel->intelScreen->front_region; + src = intel_get_rb_region(&intel_fb->Base, BUFFER_FRONT_LEFT); clipRects = dPriv->pClipRects; numClipRects = dPriv->numClipRects; } @@ -643,8 +649,13 @@ 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_fb->flip_pending) { + if (intel_fb->Base.Name == 0 && intel_rb->pf_pending == intel_fb->pf_seq) { GLuint mi_wait = MI_WAIT_FOR_EVENT; GLint pf_pipes = intel_fb->pf_pipes; BATCH_LOCALS; @@ -661,7 +672,7 @@ intel_wait_flips(struct intel_context *intel, GLuint batch_flags) OUT_BATCH(0); ADVANCE_BATCH(); - intel_fb->flip_pending = GL_FALSE; + intel_rb->pf_pending--; } } @@ -721,10 +732,14 @@ intelPageFlip(const __DRIdrawablePrivate * dPriv) intel_fb->pf_current_page = (intel->sarea->pf_current_page >> (intel_fb->pf_pipes & 0x2)) & 0x3; - driFlipRenderbuffers(intel->ctx.WinSysDrawBuffer, intel_fb->pf_current_page); - intel_draw_buffer(&intel->ctx, &intel_fb->Base); + 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_fb->flip_pending = dPriv->numClipRects != 0; + intel_flip_renderbuffers(intel_fb); + intel_draw_buffer(&intel->ctx, &intel_fb->Base); return GL_TRUE; } diff --git a/src/mesa/drivers/dri/i915tex/intel_context.c b/src/mesa/drivers/dri/i915tex/intel_context.c index 8d90489b4e8..649fe549bf4 100644 --- a/src/mesa/drivers/dri/i915tex/intel_context.c +++ b/src/mesa/drivers/dri/i915tex/intel_context.c @@ -551,27 +551,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 (irbBack && !irbBack->region) { - intel_region_reference(&irbBack->region, intel->intelScreen->back_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 (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); @@ -581,21 +584,11 @@ intelMakeCurrent(__DRIcontextPrivate * driContextPriv, } } - /* set initial GLframebuffer size to match window, if needed */ - if (drawFb->Width == 0 && driDrawPriv->w) { - _mesa_resize_framebuffer(&intel->ctx, drawFb, - driDrawPriv->w, driDrawPriv->h); - } - if (readFb->Width == 0 && 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); @@ -603,8 +596,18 @@ intelMakeCurrent(__DRIcontextPrivate * driContextPriv, intelWindowMoved(intel); } - intel_draw_buffer(&intel->ctx, drawFb); + intel_draw_buffer(&intel->ctx, &intel_fb->Base); } + + /* set initial GLframebuffer size to match window, if needed */ + if (&intel_fb->Base.Width == 0 && driDrawPriv->w) { + _mesa_resize_framebuffer(&intel->ctx, &intel_fb->Base, + driDrawPriv->w, driDrawPriv->h); + } + if (readFb->Width == 0 && driReadPriv->w) { + _mesa_resize_framebuffer(&intel->ctx, readFb, + driReadPriv->w, driReadPriv->h); + } } else { _mesa_make_current(NULL, NULL, NULL); diff --git a/src/mesa/drivers/dri/i915tex/intel_fbo.c b/src/mesa/drivers/dri/i915tex/intel_fbo.c index 104cf1d9bbf..ad078451bf2 100644 --- a/src/mesa/drivers/dri/i915tex/intel_fbo.c +++ b/src/mesa/drivers/dri/i915tex/intel_fbo.c @@ -71,22 +71,29 @@ intel_renderbuffer(struct gl_renderbuffer *rb) struct intel_renderbuffer * intel_get_renderbuffer(struct gl_framebuffer *fb, GLuint attIndex) { - if (fb->Name == 0) { - struct intel_framebuffer *intel_fb = (struct intel_framebuffer*)fb; - - if (intel_fb->pf_current_page) { - switch (attIndex) { - case BUFFER_BACK_LEFT: - attIndex = BUFFER_FRONT_LEFT; - break; - case BUFFER_FRONT_LEFT: - attIndex = BUFFER_BACK_LEFT; - break; - } - } + return intel_renderbuffer(fb->Attachment[attIndex].Renderbuffer); +} + + +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->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); } - return intel_renderbuffer(fb->Attachment[attIndex].Renderbuffer); + if (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); + } } @@ -288,10 +295,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 d55f02967f7..0446d681c61 100644 --- a/src/mesa/drivers/dri/i915tex/intel_fbo.h +++ b/src/mesa/drivers/dri/i915tex/intel_fbo.h @@ -39,11 +39,14 @@ struct intel_framebuffer { struct gl_framebuffer Base; + struct intel_renderbuffer *color_rb[3]; + /* Drawable page flipping state */ GLboolean pf_active; - GLboolean flip_pending; + GLuint pf_seq; GLint pf_pipes; GLint pf_current_page; + GLint pf_num_pages; }; @@ -63,6 +66,8 @@ 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 */ }; @@ -83,6 +88,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_screen.c b/src/mesa/drivers/dri/i915tex/intel_screen.c index f26b3f33ad2..4763d14f4f5 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; @@ -550,29 +588,40 @@ intelCreateBuffer(__DRIscreenPrivate * driScrnPriv, /* 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); + intel_set_span_functions(&intel_fb->color_rb[0]->Base); _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_FRONT_LEFT, - &frontRb->Base); + &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); + intel_set_span_functions(&intel_fb->color_rb[1]->Base); _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT, - &backRb->Base); + &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) { diff --git a/src/mesa/drivers/dri/i915tex/intel_screen.h b/src/mesa/drivers/dri/i915tex/intel_screen.h index 17698773f3d..05e2f1f2eac 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/server/i830_common.h b/src/mesa/drivers/dri/i915tex/server/i830_common.h index 06f28ed19a4..d4d58886ce0 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 -- 2.30.2