summaryrefslogtreecommitdiff
path: root/src/mesa/drivers/dri/i915tex
diff options
context:
space:
mode:
authorMichel Dänzer <michel@tungstengraphics.com>2007-02-20 19:14:23 +0100
committerMichel Dänzer <michel@tungstengraphics.com>2007-02-20 19:15:44 +0100
commite33a9d689415e00bded306699abdf93b96c0b9ad (patch)
treef34745e35dcbe54fd81e31f8a5a170e54b5d7b78 /src/mesa/drivers/dri/i915tex
parent356bf9563ed145de5ba4a14c9f23c379293f273a (diff)
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.
Diffstat (limited to 'src/mesa/drivers/dri/i915tex')
-rw-r--r--src/mesa/drivers/dri/i915tex/intel_buffers.c47
-rw-r--r--src/mesa/drivers/dri/i915tex/intel_context.c51
-rw-r--r--src/mesa/drivers/dri/i915tex/intel_fbo.c49
-rw-r--r--src/mesa/drivers/dri/i915tex/intel_fbo.h9
-rw-r--r--src/mesa/drivers/dri/i915tex/intel_screen.c65
-rw-r--r--src/mesa/drivers/dri/i915tex/intel_screen.h2
-rw-r--r--src/mesa/drivers/dri/i915tex/server/i830_common.h6
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 ec2150d27b..7db5ccfc26 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 8d90489b4e..649fe549bf 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 104cf1d9bb..ad078451bf 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 d55f02967f..0446d681c6 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 f26b3f33ad..4763d14f4f 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 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/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