*/
LOCK_HARDWARE(intel);
- if (intel->driDrawable && intel->driDrawable->numClipRects) {
+ if (dPriv && dPriv->numClipRects) {
const intelScreenPrivate *intelScreen = intel->intelScreen;
- struct gl_framebuffer *fb
- = (struct gl_framebuffer *) dPriv->driverPrivate;
+ struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
const struct intel_region *frontRegion
- = intel_get_rb_region(fb, BUFFER_FRONT_LEFT);
+ = intel_get_rb_region(&intel_fb->Base, BUFFER_FRONT_LEFT);
const struct intel_region *backRegion
- = intel_get_rb_region(fb, BUFFER_BACK_LEFT);
+ = 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;
int BR13, CMD;
int i;
- ASSERT(fb);
- ASSERT(fb->Name == 0); /* Not a user-created FBO */
+ ASSERT(intel_fb);
+ ASSERT(intel_fb->Base.Name == 0); /* Not a user-created FBO */
ASSERT(frontRegion);
ASSERT(backRegion);
ASSERT(frontRegion->pitch == backRegion->pitch);
OUT_BATCH((pbox->y1 << 16) | pbox->x1);
OUT_BATCH((pbox->y2 << 16) | pbox->x2);
- if (intel->sarea->pf_current_page == 0)
+ if (intel_fb->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);
OUT_BATCH((pbox->y1 << 16) | pbox->x1);
OUT_BATCH(BR13 & 0xffff);
- if (intel->sarea->pf_current_page == 0)
+ if (intel_fb->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);
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;
*/
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;
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 */
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);
if ((clearMask & bufBit) && !(bufBit & skipBuffers)) {
/* OK, clear this renderbuffer */
struct intel_region *irb_region =
- intel_get_rb_region(ctx->DrawBuffer, buf);
+ intel_get_rb_region(fb, buf);
struct _DriBufferObject *write_buffer =
intel_region_buffer(intel->intelScreen, irb_region,
all ? INTEL_WRITE_FULL :
_mesa_debug(ctx, "hardware blit clear buf %d rb id %d\n",
buf, irb->Base.Name);
*/
- if (intel->flip_pending) {
- /* Wait for a pending flip to take effect */
- BEGIN_BATCH(2, INTEL_BATCH_NO_CLIPRECTS);
- OUT_BATCH(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP);
- OUT_BATCH(0);
- ADVANCE_BATCH();
-
- intel->flip_pending = GL_FALSE;
- }
+ intel_wait_flips(intel, INTEL_BATCH_NO_CLIPRECTS);
BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS);
OUT_BATCH(CMD);
#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"
intelSetBackClipRects(struct intel_context *intel)
{
__DRIdrawablePrivate *dPriv = intel->driDrawable;
+ struct intel_framebuffer *intel_fb;
if (!dPriv)
return;
- if (intel->sarea->pf_active || 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;
{
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 */
}
else {
/* drawing to a window */
- switch (drawFb->_ColorDrawBufferMask[0]) {
+ switch (intel_fb->Base._ColorDrawBufferMask[0]) {
case BUFFER_BIT_FRONT_LEFT:
intelSetFrontClipRects(intel);
break;
/* Update Mesa's notion of window size */
driUpdateFramebufferSize(ctx, dPriv);
- drawFb->Initialized = GL_TRUE; /* XXX remove someday */
+ intel_fb->Base.Initialized = GL_TRUE; /* XXX remove someday */
if (intel->intelScreen->driScrnPriv->ddxMinor >= 7) {
drmI830Sarea *sarea = intel->sarea;
GLint areaA = driIntersectArea( drw_rect, pipeA_rect );
GLint areaB = driIntersectArea( drw_rect, pipeB_rect );
GLuint flags = intel->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;
+
+ pf_active = (pf_pipes & intel->sarea->pf_active) == pf_pipes;
+
+ if (1 /*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) {
+ 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)) {
+ drm_i915_flip_t flip;
+
+ flip.pipes = (intel_fb->pf_current_page ==
+ (intel->sarea->pf_current_page & 0x3)) ? 0x2 : 0x1;
+
+ drmCommandWrite(intel->driFd, DRM_I915_FLIP, &flip, sizeof(flip));
+ }
+
+ intel_fb->pf_pipes = pf_pipes;
+ }
+
+ intel_fb->pf_active = pf_active;
+ driFlipRenderbuffers(intel->ctx.WinSysDrawBuffer, intel_fb->pf_current_page);
+ 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;
} else {
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)
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;
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;
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;
{
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;
intel->vtbl.meta_draw_region(intel, screen->rotated_region, NULL); /* ? */
- if ((srcBuf == BUFFER_BIT_BACK_LEFT && intel->sarea->pf_current_page) ||
- (srcBuf == BUFFER_BIT_FRONT_LEFT && !intel->sarea->pf_current_page)) {
+ intel_fb = dPriv->driverPrivate;
+
+ if ((srcBuf == BUFFER_BIT_BACK_LEFT && intel_fb->pf_current_page) ||
+ (srcBuf == BUFFER_BIT_FRONT_LEFT && !intel_fb->pf_current_page)) {
src = intel->intelScreen->front_region;
clipRects = dPriv->pClipRects;
numClipRects = dPriv->numClipRects;
GLbitfield tri_mask = 0;
GLbitfield blit_mask = 0;
GLbitfield swrast_mask = 0;
+ struct gl_framebuffer *fb = ctx->DrawBuffer;
GLuint i;
if (0)
/* 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) {
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;
}
+/* 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;
+
+ if (intel_fb->Base.Name == 0 && intel_fb->flip_pending) {
+ 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);
+ ADVANCE_BATCH();
+
+ intel_fb->flip_pending = GL_FALSE;
+ }
+}
+
/* Flip the front & back buffers
*/
-static void
+static GLboolean
intelPageFlip(const __DRIdrawablePrivate * dPriv)
{
struct intel_context *intel;
GLboolean missed_target;
int ret;
+ struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
if (INTEL_DEBUG & DEBUG_IOCTL)
fprintf(stderr, "%s\n", __FUNCTION__);
intel = (struct intel_context *) dPriv->driContextPriv->driverPrivate;
+ if (intel->intelScreen->drmMinor < 9)
+ return GL_FALSE;
+
intelFlush(&intel->ctx);
driWaitForVBlank(dPriv, &intel->vbl_seq, intel->vblank_flags, &missed_target);
(void)(*dri_interface->getUST) (&intel->swap_missed_ust);
}
+ ret = 0;
+
LOCK_HARDWARE(intel);
- if (!dPriv->numClipRects) {
- UNLOCK_HARDWARE(intel);
- usleep(10000); /* throttle invisible client 10ms */
- return;
+ if (dPriv->numClipRects && intel_fb->pf_active) {
+ drm_i915_flip_t flip;
+
+ flip.pipes = intel_fb->pf_pipes;
+
+ ret = drmCommandWrite(intel->driFd, DRM_I915_FLIP, &flip, sizeof(flip));
}
- ret = drmCommandNone(intel->driFd, DRM_I830_FLIP);
UNLOCK_HARDWARE(intel);
- if (ret) {
- _mesa_error(&intel->ctx, GL_INVALID_OPERATION, "DRM_I830_FLIP: %d\n",
- ret);
- return;
+ if (ret || !intel_fb->pf_active)
+ return GL_FALSE;
+
+ if (!dPriv->numClipRects) {
+ usleep(10000); /* throttle invisible client 10ms */
}
- driFlipRenderbuffers(intel->ctx.WinSysDrawBuffer,
- intel->sarea->pf_current_page);
- intel_draw_buffer(&intel->ctx, intel->ctx.DrawBuffer);
+ 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);
- intel->flip_pending = GL_TRUE;
+ intel_fb->flip_pending = dPriv->numClipRects != 0;
+
+ return GL_TRUE;
}
#if 0
if (ctx->Visual.doubleBufferMode) {
intelScreenPrivate *screen = intel->intelScreen;
_mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */
- if (screen->current_rotation == 0 && intel->doPageFlip) {
- intelPageFlip(dPriv);
- }
- else {
+ if (screen->current_rotation != 0 || !intelPageFlip(dPriv)) {
intelCopyBuffer(dPriv, NULL);
}
if (screen->current_rotation != 0) {
struct intel_context;
+struct intel_framebuffer;
extern GLboolean
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);
intelWindowMoved(intel);
intel->lastStamp = dPriv->lastStamp;
}
-
- /* Update page flipping info
- */
- if (INTEL_DEBUG & DEBUG_LOCK)
- if (intel->doPageFlip != intel->sarea->pf_active)
- _mesa_printf("%s - age flipping %sactive\n", __progname,
- intel->sarea->pf_active ? "" : "in");
-
- intel->doPageFlip = intel->sarea->pf_active;
- driFlipRenderbuffers(intel->ctx.WinSysDrawBuffer,
- intel->sarea->pf_current_page);
- intel_draw_buffer(&intel->ctx, intel->ctx.DrawBuffer);
}
+
/* Lock the hardware and validate our state.
*/
void LOCK_HARDWARE( struct intel_context *intel )
int width;
int height;
int current_rotation;
-
- /* Page flipping
- */
- GLboolean doPageFlip;
- GLboolean flip_pending;
};
/* These are functions now:
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);
}
struct intel_region *
intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex)
{
- GET_CURRENT_CONTEXT(ctx);
- struct intel_context *intel = intel_context(ctx);
- struct intel_renderbuffer *irb;
-
- if (intel->sarea->pf_current_page) {
- switch (attIndex) {
- case BUFFER_BACK_LEFT:
- attIndex = BUFFER_FRONT_LEFT;
- break;
- case BUFFER_FRONT_LEFT:
- attIndex = BUFFER_BACK_LEFT;
- break;
- }
- }
-
- irb = intel_renderbuffer(fb->Attachment[attIndex].Renderbuffer);
+ struct intel_renderbuffer *irb = intel_get_renderbuffer(fb, attIndex);
if (irb)
return irb->region;
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);
}
struct intel_context;
struct intel_region;
+/**
+ * Intel framebuffer, derived from gl_framebuffer.
+ */
+struct intel_framebuffer
+{
+ struct gl_framebuffer Base;
+
+ /* Drawable page flipping state */
+ GLboolean pf_active;
+ GLboolean flip_pending;
+ GLint pf_pipes;
+ GLint pf_current_page;
+};
+
/**
* Intel renderbuffer, derived from gl_renderbuffer.
#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
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 */
{
screen->cpp,
screen->front.map);
intel_set_span_functions(&frontRb->Base);
- _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
+ _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_FRONT_LEFT,
+ &frontRb->Base);
}
if (mesaVis->doubleBufferMode) {
screen->cpp,
screen->back.map);
intel_set_span_functions(&backRb->Base);
- _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
+ _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT,
+ &backRb->Base);
}
if (mesaVis->depthBits == 24 && mesaVis->stencilBits == 8) {
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 */
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;
-
- return (driDrawPriv->driverPrivate != NULL);
+ _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 GL_TRUE;
}
}
/* _mesa_printf("%s *", __progname); */
- if (intel->flip_pending) {
- /* Wait for a pending flip to take effect */
- BEGIN_BATCH(2, batch_flags);
- OUT_BATCH(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP);
- OUT_BATCH(0);
- ADVANCE_BATCH();
-
- intel->flip_pending = GL_FALSE;
- }
+ intel_wait_flips(intel, batch_flags);
/* Emit a slot which will be filled with the inline primitive
* command later.