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.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
return intel_renderbuffer(fb->Attachment[attIndex].Renderbuffer);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user