void radeonSwapBuffers( __DRIdrawablePrivate *dPriv ) { if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) { radeonContextPtr rmesa; GLcontext *ctx; rmesa = (radeonContextPtr) dPriv->driContextPriv->driverPrivate; ctx = rmesa->glCtx; if (ctx->Visual.doubleBufferMode) { _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */ if ( rmesa->doPageFlip ) { radeonPageFlip( dPriv ); } else { radeonCopyBuffer( dPriv, NULL ); } } } else { /* XXX this shouldn't be an error but we can't handle it for now */ _mesa_problem(NULL, "%s: drawable has no context!", __FUNCTION__); } }
void radeonCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h ) { if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) { radeonContextPtr radeon; GLcontext *ctx; radeon = (radeonContextPtr) dPriv->driContextPriv->driverPrivate; ctx = radeon->glCtx; 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; _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */ radeonCopyBuffer(dPriv, &rect); } } else { /* XXX this shouldn't be an error but we can't handle it for now */ _mesa_problem(NULL, "%s: drawable has no context!", __FUNCTION__); } }
void MesaSoftwareRenderer::SwapBuffers(bool VSync) { CALLED(); if (!fBitmap) return; if (fVisual->doubleBufferMode) _mesa_notifySwapBuffers(fContext); if (!fDirectModeEnabled || fInfo == NULL) { if (GLView()->LockLooperWithTimeout(1000) == B_OK) { GLView()->DrawBitmap(fBitmap, B_ORIGIN); GLView()->UnlockLooper(); } } else { // TODO: Here the BGLView needs to be drawlocked. _CopyToDirect(); } if (VSync) { BScreen screen(GLView()->Window()); screen.WaitForRetrace(); } }
BOOL sw_SwapBuffers(HDC hdc, struct wgl_dc_data* dc_data) { struct sw_framebuffer* fb = dc_data->sw_data; struct sw_context* sw_ctx = (struct sw_context*)IntGetCurrentDHGLRC(); /* Notify mesa */ if(sw_ctx) _mesa_notifySwapBuffers(&sw_ctx->mesa); if(!(fb->flags & SW_FB_DOUBLEBUFFERED)) return TRUE; /* Upload to the display */ return (SetDIBitsToDevice(hdc, 0, 0, fb->bmi.bmiHeader.biWidth, fb->bmi.bmiHeader.biHeight, 0, 0, 0, fb->bmi.bmiHeader.biHeight, fb->backbuffer.Buffer, &fb->bmi, DIB_RGB_COLORS) != 0); }
/* * Swap front/back buffers for current context if double buffered. */ void GLAPIENTRY fxMesaSwapBuffers(void) { if (TDFX_DEBUG & VERBOSE_DRIVER) { fprintf(stderr, "fxMesaSwapBuffers()\n"); } if (fxMesaCurrentCtx) { _mesa_notifySwapBuffers(fxMesaCurrentCtx->glCtx); if (fxMesaCurrentCtx->haveDoubleBuffer) { grBufferSwap(fxMesaCurrentCtx->swapInterval); #if 0 /* * Don't allow swap buffer commands to build up! */ while (FX_grGetInteger(GR_PENDING_BUFFERSWAPS) > fxMesaCurrentCtx->maxPendingSwapBuffers) /* The driver is able to sleep when waiting for the completation of multiple swapbuffer operations instead of wasting CPU time (NOTE: you must uncomment the following line in the in order to enable this option) */ /* usleep(10000); */ ; #endif fxMesaCurrentCtx->stats.swapBuffer++; } } }
void DMesaSwapBuffers (DMesaBuffer buffer) { /* copy/swap back buffer to front if applicable */ GET_CURRENT_CONTEXT(ctx); _mesa_notifySwapBuffers(ctx); vl_flip(); (void)buffer; }
void MesaDriver::SwapBuffers() const { _mesa_notifySwapBuffers(m_glcontext); if (m_bitmap) { m_bglview->LockLooper(); m_bglview->DrawBitmap(m_bitmap); m_bglview->UnlockLooper(); }; }
/* * Copy the back buffer to the front buffer. If there's no back buffer * this is a no-op. */ PUBLIC void XMesaSwapBuffers( XMesaBuffer b ) { GET_CURRENT_CONTEXT(ctx); if (!b->backxrb) { /* single buffered */ return; } /* If we're swapping the buffer associated with the current context * we have to flush any pending rendering commands first. */ if (ctx && ctx->DrawBuffer == &(b->mesa_buffer)) _mesa_notifySwapBuffers(ctx); if (b->db_mode) { if (b->backxrb->ximage) { /* Copy Ximage (back buf) from client memory to server window */ #if defined(USE_XSHM) if (b->shm) { /*_glthread_LOCK_MUTEX(_xmesa_lock);*/ XShmPutImage( b->xm_visual->display, b->frontxrb->drawable, b->swapgc, b->backxrb->ximage, 0, 0, 0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height, False ); /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/ } else #endif { /*_glthread_LOCK_MUTEX(_xmesa_lock);*/ XMesaPutImage( b->xm_visual->display, b->frontxrb->drawable, b->swapgc, b->backxrb->ximage, 0, 0, 0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height ); /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/ } } else if (b->backxrb->pixmap) { /* Copy pixmap (back buf) to window (front buf) on server */ /*_glthread_LOCK_MUTEX(_xmesa_lock);*/ XMesaCopyArea( b->xm_visual->display, b->backxrb->pixmap, /* source drawable */ b->frontxrb->drawable, /* dest. drawable */ b->swapgc, 0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height, 0, 0 /* dest region */ ); /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/ } } XSync( b->xm_visual->display, False ); }
void MesaSoftwareRenderer::SwapBuffers(bool VSync) { CALLED(); if (!fBitmap) return; if (fVisual->doubleBufferMode) _mesa_notifySwapBuffers(fContext); if (!fDirectModeEnabled || fInfo == NULL) { if (GLView()->LockLooperWithTimeout(1000) == B_OK) { GLView()->DrawBitmap(fBitmap, B_ORIGIN); GLView()->UnlockLooper(); } return; } BAutolock lock(fInfoLocker); // check the bitmap size still matches the size if (fInfo->window_bounds.bottom - fInfo->window_bounds.top != fBitmap->Bounds().IntegerHeight() || fInfo->window_bounds.right - fInfo->window_bounds.left != fBitmap->Bounds().IntegerWidth()) return; uint8 bytesPerPixel = fInfo->bits_per_pixel / 8; uint32 bytesPerRow = fBitmap->BytesPerRow(); for (uint32 i = 0; i < fInfo->clip_list_count; i++) { clipping_rect *clip = &fInfo->clip_list[i]; int32 height = clip->bottom - clip->top + 1; int32 bytesWidth = (clip->right - clip->left + 1) * bytesPerPixel; uint8 *p = (uint8 *)fInfo->bits + clip->top * fInfo->bytes_per_row + clip->left * bytesPerPixel; uint8 *b = (uint8 *)fBitmap->Bits() + (clip->top - fInfo->window_bounds.top) * bytesPerRow + (clip->left - fInfo->window_bounds.left) * bytesPerPixel; for (int y = 0; y < height; y++) { memcpy(p, b, bytesWidth); p += fInfo->bytes_per_row; b += bytesPerRow; } } if (VSync) { BScreen screen(GLView()->Window()); screen.WaitForRetrace(); } }
/* * Copy sub-region of back buffer to front buffer */ void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height ) { GET_CURRENT_CONTEXT(ctx); /* If we're swapping the buffer associated with the current context * we have to flush any pending rendering commands first. */ if (ctx && ctx->DrawBuffer == &(b->mesa_buffer)) _mesa_notifySwapBuffers(ctx); if (!b->backxrb) { /* single buffered */ return; } if (b->db_mode) { int yTop = b->mesa_buffer.Height - y - height; if (b->backxrb->ximage) { /* Copy Ximage from host's memory to server's window */ #if defined(USE_XSHM) if (b->shm) { /* XXX assuming width and height aren't too large! */ XShmPutImage( b->xm_visual->display, b->frontxrb->drawable, b->swapgc, b->backxrb->ximage, x, yTop, x, yTop, width, height, False ); /* wait for finished event??? */ } else #endif { /* XXX assuming width and height aren't too large! */ XMesaPutImage( b->xm_visual->display, b->frontxrb->drawable, b->swapgc, b->backxrb->ximage, x, yTop, x, yTop, width, height ); } } else { /* Copy pixmap to window on server */ XMesaCopyArea( b->xm_visual->display, b->backxrb->pixmap, /* source drawable */ b->frontxrb->drawable, /* dest. drawable */ b->swapgc, x, yTop, width, height, /* source region */ x, yTop /* dest region */ ); } } }
/* If the backbuffer is on a videocard, this is extraordinarily slow! */ static EGLBoolean fbSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw) { fbContext *context = (fbContext *)_eglGetCurrentContext(); fbSurface *fs = Lookup_fbSurface(draw); struct gl_renderbuffer * front_renderbuffer = fs->mesa_framebuffer->Attachment[BUFFER_FRONT_LEFT].Renderbuffer; void *frontBuffer = front_renderbuffer->Data; int currentPitch = ((driRenderbuffer *)front_renderbuffer)->pitch; void *backBuffer = fs->mesa_framebuffer->Attachment[BUFFER_BACK_LEFT].Renderbuffer->Data; if (!_eglSwapBuffers(drv, dpy, draw)) return EGL_FALSE; if (context) { GLcontext *ctx = context->glCtx; if (ctx->Visual.doubleBufferMode) { int i; int offset = 0; char *tmp = _mesa_malloc(currentPitch); _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */ ASSERT(frontBuffer); ASSERT(backBuffer); for (i = 0; i < fs->Base.Height; i++) { _mesa_memcpy(tmp, (char *) backBuffer + offset, currentPitch); _mesa_memcpy((char *) frontBuffer + offset, tmp, currentPitch); offset += currentPitch; } _mesa_free(tmp); } } else { /* XXX this shouldn't be an error but we can't handle it for now */ _mesa_problem(NULL, "fbSwapBuffers: drawable has no context!\n"); return EGL_FALSE; } return EGL_TRUE; }
/* If the backbuffer is on a videocard, this is extraordinarily slow! */ static void fbSwapBuffers( __DRIdrawablePrivate *dPriv ) { struct gl_framebuffer *mesa_framebuffer = (struct gl_framebuffer *)dPriv->driverPrivate; struct gl_renderbuffer * front_renderbuffer = mesa_framebuffer->Attachment[BUFFER_FRONT_LEFT].Renderbuffer; void *frontBuffer = front_renderbuffer->Data; int currentPitch = ((driRenderbuffer *)front_renderbuffer)->pitch; void *backBuffer = mesa_framebuffer->Attachment[BUFFER_BACK_LEFT].Renderbuffer->Data; if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) { fbContextPtr fbmesa = (fbContextPtr) dPriv->driContextPriv->driverPrivate; GLcontext *ctx = fbmesa->glCtx; if (ctx->Visual.doubleBufferMode) { int i; int offset = 0; char *tmp = _mesa_malloc(currentPitch); _mesa_notifySwapBuffers( ctx ); /* flush pending rendering commands */ ASSERT(frontBuffer); ASSERT(backBuffer); for (i = 0; i < dPriv->h; i++) { _mesa_memcpy(tmp, (char *) backBuffer + offset, currentPitch); _mesa_memcpy((char *) frontBuffer + offset, tmp, currentPitch); offset += currentPitch; } _mesa_free(tmp); } } else { /* XXX this shouldn't be an error but we can't handle it for now */ _mesa_problem(NULL, "fbSwapBuffers: drawable has no context!\n"); } }
void glFBDevSwapBuffers( GLFBDevBufferPtr buffer ) { GLFBDevContextPtr fbdevctx = glFBDevGetCurrentContext(); struct GLFBDevRenderbufferRec *frontrb = (struct GLFBDevRenderbufferRec *) buffer->glframebuffer.Attachment[BUFFER_FRONT_LEFT].Renderbuffer; struct GLFBDevRenderbufferRec *backrb = (struct GLFBDevRenderbufferRec *) buffer->glframebuffer.Attachment[BUFFER_BACK_LEFT].Renderbuffer; if (!buffer || !buffer->visual->glvisual.doubleBufferMode) return; /* check if swapping currently bound buffer */ if (fbdevctx->drawBuffer == buffer) { /* flush pending rendering */ _mesa_notifySwapBuffers(&fbdevctx->glcontext); } ASSERT(frontrb->Base.Data); ASSERT(backrb->Base.Data); memcpy(frontrb->Base.Data, backrb->Base.Data, buffer->size); }
/* * Swap front/back buffers for current context if double buffered. */ void ggiMesaSwapBuffers(void) { GLcontext *ctx; ggi_mesa_context_t ggi_ctx; ctx = _mesa_get_current_context(); ggi_ctx = (ggi_mesa_context_t)ctx->DriverCtx; GGIMESADPRINT_CORE("ggiMesaSwapBuffers() called\n"); _mesa_notifySwapBuffers(ctx); gl_ggiFlush(ctx); ggiSetDisplayFrame(ggi_ctx->ggi_visual, !ggiGetDisplayFrame(ggi_ctx->ggi_visual)); ggiSetWriteFrame(ggi_ctx->ggi_visual, !ggiGetWriteFrame(ggi_ctx->ggi_visual)); ggiSetReadFrame(ggi_ctx->ggi_visual, !ggiGetReadFrame(ggi_ctx->ggi_visual)); GGIMESADPRINT_CORE("swap disp: %d, write %d\n", ggiGetDisplayFrame(ggi_ctx->ggi_visual), ggiGetWriteFrame(ggi_ctx->ggi_visual)); }
static void dri_swap_buffers(__DRIdrawable * dPriv) { __DRIscreen *sPriv = dPriv->driScreenPriv; GET_CURRENT_CONTEXT(ctx); struct dri_drawable *drawable = dri_drawable(dPriv); struct gl_framebuffer *fb; struct swrast_renderbuffer *frontrb, *backrb; TRACE; fb = &drawable->Base; frontrb = swrast_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer); backrb = swrast_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer); /* check for signle-buffered */ if (backrb == NULL) return; /* check if swapping currently bound buffer */ if (ctx && ctx->DrawBuffer == fb) { /* flush pending rendering */ _mesa_notifySwapBuffers(ctx); } sPriv->swrast_loader->putImage(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP, 0, 0, frontrb->Base.Width, frontrb->Base.Height, backrb->Base.Data, dPriv->loaderPrivate); }
/* * Correct a drawablePrivate's set of vblank flags WRT the current context. * When considering multiple crtcs. */ GLuint intelFixupVblank(struct intel_context *intel, __DRIdrawablePrivate *dPriv) { if (!intel->intelScreen->driScrnPriv->dri2.enabled && intel->intelScreen->driScrnPriv->ddx_version.minor >= 7) { volatile drm_i915_sarea_t *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 }; drm_clip_rect_t planeA_rect = { .x1 = sarea->planeA_x, .y1 = sarea->planeA_y, .x2 = sarea->planeA_x + sarea->planeA_w, .y2 = sarea->planeA_y + sarea->planeA_h }; drm_clip_rect_t planeB_rect = { .x1 = sarea->planeB_x, .y1 = sarea->planeB_y, .x2 = sarea->planeB_x + sarea->planeB_w, .y2 = sarea->planeB_y + sarea->planeB_h }; GLint areaA = driIntersectArea( drw_rect, planeA_rect ); GLint areaB = driIntersectArea( drw_rect, planeB_rect ); GLuint flags = dPriv->vblFlags; /* Update vblank info */ if (areaB > areaA || (areaA == areaB && areaB > 0)) { flags = dPriv->vblFlags | VBLANK_FLAG_SECONDARY; } else { flags = dPriv->vblFlags & ~VBLANK_FLAG_SECONDARY; } /* Do the stupid test: Is one of them actually disabled? */ if (sarea->planeA_w == 0 || sarea->planeA_h == 0) { flags = dPriv->vblFlags | VBLANK_FLAG_SECONDARY; } else if (sarea->planeB_w == 0 || sarea->planeB_h == 0) { flags = dPriv->vblFlags & ~VBLANK_FLAG_SECONDARY; } return flags; } else { return dPriv->vblFlags & ~VBLANK_FLAG_SECONDARY; } } /** * Called from driSwapBuffers() */ void intelSwapBuffers(__DRIdrawablePrivate * dPriv) { __DRIscreenPrivate *psp = dPriv->driScreenPriv; if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) { GET_CURRENT_CONTEXT(ctx); struct intel_context *intel; if (ctx == NULL) return; intel = intel_context(ctx); if (ctx->Visual.doubleBufferMode) { GLboolean missed_target; struct intel_framebuffer *intel_fb = dPriv->driverPrivate; int64_t ust; _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */ /* * The old swapping ioctl was incredibly racy, just wait for vblank * and do the swap ourselves. */ driWaitForVBlank(dPriv, &missed_target); /* * Update each buffer's vbl_pending so we don't get too out of * sync */ intel_get_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT)->vbl_pending = dPriv->vblSeq; intel_get_renderbuffer(&intel_fb->Base, BUFFER_FRONT_LEFT)->vbl_pending = dPriv->vblSeq; intelCopyBuffer(dPriv, NULL); intel_fb->swap_count++; (*psp->systemTime->getUST) (&ust); if (missed_target) { intel_fb->swap_missed_count++; intel_fb->swap_missed_ust = ust - intel_fb->swap_ust; } intel_fb->swap_ust = ust; } drmCommandNone(intel->driFd, DRM_I915_GEM_THROTTLE); } else { /* XXX this shouldn't be an error but we can't handle it for now */ fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__); } } /** * Called from driCopySubBuffer() */ void intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h) { if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) { struct intel_context *intel = (struct intel_context *) dPriv->driContextPriv->driverPrivate; GLcontext *ctx = &intel->ctx; 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; _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */ intelCopyBuffer(dPriv, &rect); } } else { /* XXX this shouldn't be an error but we can't handle it for now */ fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__); } } /** * This will be called whenever the currently bound window is moved/resized. * XXX: actually, it seems to NOT be called when the window is only moved (BP). */ void intelWindowMoved(struct intel_context *intel) { GLcontext *ctx = &intel->ctx; __DRIdrawablePrivate *dPriv = intel->driDrawable; struct intel_framebuffer *intel_fb = dPriv->driverPrivate; if (!intel->intelScreen->driScrnPriv->dri2.enabled && intel->intelScreen->driScrnPriv->ddx_version.minor >= 7) { GLuint flags = intelFixupVblank(intel, dPriv); /* Check to see if we changed pipes */ if (flags != dPriv->vblFlags && dPriv->vblFlags && !(dPriv->vblFlags & VBLANK_FLAG_NO_IRQ)) { int64_t count; drmVBlank vbl; int i; /* * Deal with page flipping */ vbl.request.type = DRM_VBLANK_ABSOLUTE; if ( dPriv->vblFlags & VBLANK_FLAG_SECONDARY ) { vbl.request.type |= DRM_VBLANK_SECONDARY; } for (i = 0; i < 2; 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); } /* * Update msc_base from old pipe */ driDrawableGetMSC32(dPriv->driScreenPriv, dPriv, &count); dPriv->msc_base = count; /* * Then get new vblank_base and vblSeq values */ dPriv->vblFlags = flags; driGetCurrentVBlank(dPriv); dPriv->vblank_base = dPriv->vblSeq; intel_fb->vbl_waited = dPriv->vblSeq; for (i = 0; i < 2; i++) { if (intel_fb->color_rb[i]) intel_fb->color_rb[i]->vbl_pending = intel_fb->vbl_waited; } } } else { dPriv->vblFlags &= ~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 */ if (ctx->Driver.Scissor != NULL) { ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y, ctx->Scissor.Width, ctx->Scissor.Height); } /* Re-calculate viewport related state */ if (ctx->Driver.DepthRange != NULL) ctx->Driver.DepthRange( ctx, ctx->Viewport.Near, ctx->Viewport.Far ); }