#include "vblank.h"
+/* This block can be removed when libdrm >= 2.3.1 is required */
+
+#ifndef DRM_VBLANK_FLIP
+
+#define DRM_VBLANK_FLIP 0x8000000
+
+typedef struct drm_i915_flip {
+ int pipes;
+} drm_i915_flip_t;
+
+#undef DRM_IOCTL_I915_FLIP
+#define DRM_IOCTL_I915_FLIP DRM_IOW(DRM_COMMAND_BASE + DRM_I915_FLIP, \
+ drm_i915_flip_t)
+
+#endif
+
+
/**
* XXX move this into a new dri/common/cliprects.c file.
*/
/**
- * Update the following fields for rendering to a user-created FBO:
+ * Update the following fields for rendering:
* intel->numClipRects
* intel->pClipRects
- * intel->drawX
- * intel->drawY
*/
static void
intelSetRenderbufferClipRects(struct intel_context *intel)
{
+ /* zero-sized buffers might be legal? */
assert(intel->ctx.DrawBuffer->Width > 0);
assert(intel->ctx.DrawBuffer->Height > 0);
intel->fboRect.x1 = 0;
intel->fboRect.y2 = intel->ctx.DrawBuffer->Height;
intel->numClipRects = 1;
intel->pClipRects = &intel->fboRect;
- intel->drawX = 0;
- intel->drawY = 0;
-}
-
-
-/**
- * As above, but for rendering to front buffer of a window.
- * \sa intelSetRenderbufferClipRects
- */
-static void
-intelSetFrontClipRects(struct intel_context *intel)
-{
- __DRIdrawablePrivate *dPriv = intel->driDrawable;
-
- if (!dPriv)
- return;
-
- intel->numClipRects = dPriv->numClipRects;
- intel->pClipRects = dPriv->pClipRects;
- intel->drawX = dPriv->x;
- intel->drawY = dPriv->y;
-}
-
-
-/**
- * As above, but for rendering to back buffer of a window.
- */
-static void
-intelSetBackClipRects(struct intel_context *intel)
-{
- __DRIdrawablePrivate *dPriv = intel->driDrawable;
- struct intel_framebuffer *intel_fb;
-
- if (!dPriv)
- return;
-
- 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;
- intel->drawX = dPriv->x;
- intel->drawY = dPriv->y;
- }
- else {
- /* use the back clip rects */
- intel->numClipRects = dPriv->numBackClipRects;
- intel->pClipRects = dPriv->pBackClipRects;
- intel->drawX = dPriv->backX;
- intel->drawY = dPriv->backY;
- }
}
if (!intel->ctx.DrawBuffer) {
/* when would this happen? -BP */
- intelSetFrontClipRects(intel);
- }
- else if (intel->ctx.DrawBuffer->Name != 0) {
- /* drawing to user-created FBO - do nothing */
- /* Cliprects would be set from intelDrawBuffer() */
- }
- else {
- /* drawing to a window */
- switch (intel_fb->Base._ColorDrawBufferMask[0]) {
- case BUFFER_BIT_FRONT_LEFT:
- intelSetFrontClipRects(intel);
- break;
- case BUFFER_BIT_BACK_LEFT:
- intelSetBackClipRects(intel);
- break;
- default:
- /* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */
- intelSetFrontClipRects(intel);
- }
+ assert(0);
+ intel->numClipRects = 0;
}
- if (intel->intelScreen->driScrnPriv->ddxMinor >= 7) {
+ /* Update Mesa's notion of window size */
+ driUpdateFramebufferSize(ctx, dPriv);
+ intel_fb->Base.Initialized = GL_TRUE; /* XXX remove someday */
+
+ {
drmI830Sarea *sarea = intel->sarea;
drm_clip_rect_t drw_rect = { .x1 = dPriv->x, .x2 = dPriv->x + dPriv->w,
.y1 = dPriv->y, .y2 = dPriv->y + dPriv->h };
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;
+ intel_fb->pf_num_pages = 2 /*intel->intelScreen->third.handle ? 3 : 2*/;
pf_active = pf_pipes && (pf_pipes & intel->sarea->pf_active) == pf_pipes;
pf_active ? "" : "in");
if (pf_active) {
- 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++) {
+ 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;
- flip.pipes = (intel_fb->pf_current_page ==
- (intel->sarea->pf_current_page & 0x3)) ? 0x2 : 0x1;
+ 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));
}
flags = intel_fb->vblank_flags & ~VBLANK_FLAG_SECONDARY;
}
- if (flags != intel_fb->vblank_flags) {
+ if (flags != intel_fb->vblank_flags && intel_fb->vblank_flags &&
+ !(intel_fb->vblank_flags & VBLANK_FLAG_NO_IRQ)) {
+ 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++) {
+ if (!intel_fb->color_rb[i] ||
+ (intel_fb->vbl_waited - intel_fb->color_rb[i]->vbl_pending) <=
+ (1<<23))
+ continue;
+
+ 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++) {
+ if (intel_fb->color_rb[i])
+ intel_fb->color_rb[i]->vbl_pending = intel_fb->vbl_waited;
+ }
}
- } else {
- 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);
LOCK_HARDWARE(intel);
- /* XXX FBO: was: intel->driDrawable->numClipRects */
if (intel->numClipRects) {
- GLint cx, cy, cw, ch;
GLuint buf;
intel->vtbl.install_meta_state(intel);
- /* Get clear bounds after locking */
- 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;
- clear.y1 = cy;
- clear.x2 = cx + cw;
- clear.y2 = cy + ch;
+ clear.x1 = fb->_Xmin;
+ clear.y1 = fb->_Ymin;
+ clear.x2 = fb->_Xmax;
+ clear.y2 = fb->_Ymax;
/* Back and stencil cliprects are the same. Try and do both
* buffers at once:
/* XXX: Using INTEL_BATCH_NO_CLIPRECTS here is dangerous as the
* drawing origin may not be correctly emitted.
*/
- intel_meta_draw_quad(intel, clear.x1, clear.x2, clear.y1, clear.y2, intel->ctx.Depth.Clear, clearColor, 0, 0, 0, 0); /* texcoords */
+ intel_meta_draw_quad(intel, clear.x1, clear.x2, clear.y1, clear.y2,
+ intel->ctx.Depth.Clear, clearColor, 0, 0, 0, 0); /* texcoords */
mask &=
~(BUFFER_BIT_BACK_LEFT | BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH);
}
-
-
-/**
- * Copy the window contents named by dPriv to the rotated (or reflected)
- * color buffer.
- * srcBuf is BUFFER_BIT_FRONT_LEFT or BUFFER_BIT_BACK_LEFT to indicate the source.
- */
-void
-intelRotateWindow(struct intel_context *intel,
- __DRIdrawablePrivate * dPriv, GLuint srcBuf)
-{
- 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;
- int i;
- GLenum format, type;
-
- int xOrig, yOrig;
- int origNumClipRects;
- drm_clip_rect_t *origRects;
-
- /*
- * set up hardware state
- */
- intelFlush(&intel->ctx);
-
- LOCK_HARDWARE(intel);
-
- if (!intel->numClipRects) {
- UNLOCK_HARDWARE(intel);
- return;
- }
-
- intel->vtbl.install_meta_state(intel);
-
- intel->vtbl.meta_no_depth_write(intel);
- intel->vtbl.meta_no_stencil_write(intel);
- intel->vtbl.meta_color_mask(intel, GL_FALSE);
-
-
- /* save current drawing origin and cliprects (restored at end) */
- xOrig = intel->drawX;
- yOrig = intel->drawY;
- origNumClipRects = intel->numClipRects;
- origRects = intel->pClipRects;
-
- /*
- * set drawing origin, cliprects for full-screen access to rotated screen
- */
- fullRect.x1 = 0;
- fullRect.y1 = 0;
- fullRect.x2 = screen->rotatedWidth;
- fullRect.y2 = screen->rotatedHeight;
- intel->drawX = 0;
- intel->drawY = 0;
- intel->numClipRects = 1;
- intel->pClipRects = &fullRect;
-
- intel->vtbl.meta_draw_region(intel, screen->rotated_region, NULL); /* ? */
-
- 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;
- type = GL_UNSIGNED_BYTE;
- }
- else {
- format = GL_BGR;
- type = GL_UNSIGNED_SHORT_5_6_5_REV;
- }
-
- /* set the whole screen up as a texture to avoid alignment issues */
- intel->vtbl.meta_tex_rect_source(intel,
- src->buffer,
- screen->width,
- screen->height, src->pitch, format, type);
-
- intel->vtbl.meta_texture_blend_replace(intel);
-
- /*
- * loop over the source window's cliprects
- */
- for (i = 0; i < numClipRects; i++) {
- int srcX0 = clipRects[i].x1;
- int srcY0 = clipRects[i].y1;
- int srcX1 = clipRects[i].x2;
- int srcY1 = clipRects[i].y2;
- GLfloat verts[4][2], tex[4][2];
- int j;
-
- /* build vertices for four corners of clip rect */
- verts[0][0] = srcX0;
- verts[0][1] = srcY0;
- verts[1][0] = srcX1;
- verts[1][1] = srcY0;
- verts[2][0] = srcX1;
- verts[2][1] = srcY1;
- verts[3][0] = srcX0;
- verts[3][1] = srcY1;
-
- /* .. and texcoords */
- tex[0][0] = srcX0;
- tex[0][1] = srcY0;
- tex[1][0] = srcX1;
- tex[1][1] = srcY0;
- tex[2][0] = srcX1;
- tex[2][1] = srcY1;
- tex[3][0] = srcX0;
- tex[3][1] = srcY1;
-
- /* transform coords to rotated screen coords */
-
- for (j = 0; j < 4; j++) {
- matrix23TransformCoordf(&screen->rotMatrix,
- &verts[j][0], &verts[j][1]);
- }
-
- /* draw polygon to map source image to dest region */
- intel_meta_draw_poly(intel, 4, verts, 0, 0, tex);
-
- } /* cliprect loop */
-
- intel->vtbl.leave_meta_state(intel);
- intel_batchbuffer_flush(intel->batch);
-
- /* restore original drawing origin and cliprects */
- intel->drawX = xOrig;
- intel->drawY = yOrig;
- intel->numClipRects = origNumClipRects;
- intel->pClipRects = origRects;
-
- UNLOCK_HARDWARE(intel);
-}
-
-
/**
* Called by ctx->Driver.Clear.
*/
BUFFER_BACK_LEFT);
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;
- if (pf_pipes & 0x1)
- mi_wait |= MI_WAIT_FOR_PLANE_A_FLIP;
-
- if (pf_pipes & 0x2)
- mi_wait |= MI_WAIT_FOR_PLANE_B_FLIP;
-
/* Wait for pending flips to take effect */
BEGIN_BATCH(2, batch_flags);
- OUT_BATCH(mi_wait);
- OUT_BATCH(0);
+ 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--;
}
}
-
+#if 0
/* Flip the front & back buffers
*/
static GLboolean
intel_flip_renderbuffers(intel_fb);
intel_draw_buffer(&intel->ctx, &intel_fb->Base);
+ if (INTEL_DEBUG & DEBUG_IOCTL)
+ fprintf(stderr, "%s: success\n", __FUNCTION__);
+
return GL_TRUE;
}
+#endif
-#if 0
-void
-intelSwapBuffers(__DRIdrawablePrivate * dPriv)
-{
- if (dPriv->driverPrivate) {
- const struct gl_framebuffer *fb
- = (struct gl_framebuffer *) dPriv->driverPrivate;
- if (fb->Visual.doubleBufferMode) {
- GET_CURRENT_CONTEXT(ctx);
- if (ctx && ctx->DrawBuffer == fb) {
- _mesa_notifySwapBuffers(ctx); /* flush pending rendering */
- }
- if (intel->doPageFlip) {
- intelPageFlip(dPriv);
- }
- else {
- intelCopyBuffer(dPriv);
- }
- }
- }
- else {
- _mesa_problem(NULL,
- "dPriv has no gl_framebuffer pointer in intelSwapBuffers");
- }
-}
-#else
-/* Trunk version:
- */
static GLboolean
intelScheduleSwap(const __DRIdrawablePrivate * dPriv, GLboolean *missed_target)
drm_i915_vblank_swap_t swap;
GLboolean ret;
- if ((intel_fb->vblank_flags & VBLANK_FLAG_NO_IRQ) ||
- intelScreen->current_rotation != 0 ||
+ if (!intel_fb->vblank_flags ||
+ (intel_fb->vblank_flags & VBLANK_FLAG_NO_IRQ) ||
intelScreen->drmMinor < (intel_fb->pf_active ? 9 : 6))
return GL_FALSE;
swap.sequence -= target;
*missed_target = swap.sequence > 0 && swap.sequence <= (1 << 23);
- if (swap.seqtype & DRM_VBLANK_FLIP) {
+ intel_get_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT)->vbl_pending =
intel_get_renderbuffer(&intel_fb->Base,
BUFFER_FRONT_LEFT)->vbl_pending =
- intel_get_renderbuffer(&intel_fb->Base,
- BUFFER_BACK_LEFT)->vbl_pending = intel_fb->vbl_seq;
+ intel_fb->vbl_seq;
+ if (swap.seqtype & DRM_VBLANK_FLIP) {
intel_flip_renderbuffers(intel_fb);
intel_draw_buffer(&intel->ctx, intel->ctx.DrawBuffer);
}
return ret;
}
-
+
void
intelSwapBuffers(__DRIdrawablePrivate * dPriv)
{
intel = intel_context(ctx);
if (ctx->Visual.doubleBufferMode) {
- intelScreenPrivate *screen = intel->intelScreen;
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)) {
+ if (!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);
- }
+ intelCopyBuffer(dPriv, NULL);
}
intel_fb->swap_count++;
fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__);
}
}
-#endif
void
intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h)
if (ctx->Visual.doubleBufferMode) {
drm_clip_rect_t rect;
- rect.x1 = x + dPriv->x;
- rect.y1 = (dPriv->h - y - h) + dPriv->y;
- rect.x2 = rect.x1 + w;
- rect.y2 = rect.y1 + h;
+ /* fixup cliprect (driDrawable may have changed?) later */
+ rect.x1 = x;
+ rect.y1 = y;
+ rect.x2 = w;
+ rect.y2 = h;
_mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */
intelCopyBuffer(dPriv, &rect);
}
struct intel_context *intel = intel_context(ctx);
struct intel_region *colorRegion, *depthRegion = NULL;
struct intel_renderbuffer *irbDepth = NULL, *irbStencil = NULL;
- int front = 0; /* drawing to front color buffer? */
if (!fb) {
/* this can happen during the initial context initialization */
return;
}
- /* Do this here, note core Mesa, since this function is called from
+ /* Do this here, not core Mesa, since this function is called from
* many places within the driver.
*/
if (ctx->NewState & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) {
/*
* How many color buffers are we drawing into?
*/
- if (fb->_NumColorDrawBuffers[0] != 1
-#if 0
- /* XXX FBO temporary - always use software rendering */
- || 1
-#endif
- ) {
+ if (fb->_NumColorDrawBuffers[0] != 1) {
/* writing to 0 or 2 or 4 color buffers */
/*_mesa_debug(ctx, "Software rendering\n");*/
FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE);
- front = 1; /* might not have back color buffer */
}
else {
/* draw to exactly one color buffer */
/*_mesa_debug(ctx, "Hardware rendering\n");*/
FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE);
- if (fb->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT) {
- front = 1;
- }
}
/*
* Get the intel_renderbuffer for the colorbuffer we're drawing into.
* And set up cliprects.
*/
- if (fb->Name == 0) {
- /* drawing to window system buffer */
- if (front) {
- intelSetFrontClipRects(intel);
- colorRegion = intel_get_rb_region(fb, BUFFER_FRONT_LEFT);
- }
- else {
- intelSetBackClipRects(intel);
- colorRegion = intel_get_rb_region(fb, BUFFER_BACK_LEFT);
- }
- }
- else {
- /* drawing to user-created FBO */
+ {
struct intel_renderbuffer *irb;
intelSetRenderbufferClipRects(intel);
irb = intel_renderbuffer(fb->_ColorDrawBuffers[0][0]);
/**
** Release old regions, reference new regions
**/
-#if 0 /* XXX FBO: this seems to be redundant with i915_state_draw_region() */
- if (intel->draw_region != colorRegion) {
- intel_region_release(&intel->draw_region);
- intel_region_reference(&intel->draw_region, colorRegion);
- }
- if (intel->intelScreen->depth_region != depthRegion) {
- intel_region_release(&intel->intelScreen->depth_region);
- intel_region_reference(&intel->intelScreen->depth_region, depthRegion);
- }
-#endif
intel->vtbl.set_draw_region(intel, colorRegion, depthRegion);