Start re-working SwapBuffers.

intelCopyBuffer() is now intelDisplayBuffer(): it displays the given surface
in the on-screen window.
Added a pipe_surface parameter to winsys->flush_frontbuffer().
Front buffer rendering/flushing actually works now.
But, we should only allocate the front surface on demand...
This commit is contained in:
Brian 2007-11-01 18:37:00 -06:00
parent 28bed6d355
commit d8e66aca84
6 changed files with 64 additions and 52 deletions

View file

@ -58,15 +58,33 @@ typedef struct drm_i915_flip {
#endif
/**
* Return the pipe_surface for the given renderbuffer.
*/
static struct pipe_surface *
get_color_surface(struct intel_framebuffer *intel_fb,
GLuint bufferIndex)
{
struct st_renderbuffer *strb
= st_renderbuffer(intel_fb->Base.Attachment[bufferIndex].Renderbuffer);
if (strb)
return strb->surface;
return NULL;
}
/**
* Copy the back color buffer to the front color buffer.
* Used for SwapBuffers().
* Display a colorbuffer surface in an X window.
* Used for SwapBuffers and flushing front buffer rendering.
*
* \param dPriv the window/drawable to display into
* \param surf the surface to display
* \param rect optional subrect of surface to display (may be NULL).
*/
void
intelCopyBuffer(__DRIdrawablePrivate * dPriv,
const drm_clip_rect_t * rect)
intelDisplayBuffer(__DRIdrawablePrivate * dPriv,
struct pipe_surface *surf,
const drm_clip_rect_t * rect)
{
struct intel_context *intel;
@ -103,49 +121,24 @@ intelCopyBuffer(__DRIdrawablePrivate * dPriv,
if (dPriv && dPriv->numClipRects) {
struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
#if 0
const struct pipe_region *backRegion
= intel_fb->Base._ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT ?
intel_get_rb_region(&intel_fb->Base, BUFFER_FRONT_LEFT) :
intel_get_rb_region(&intel_fb->Base, BUFFER_BACK_LEFT);
#endif
const int backWidth = intel_fb->Base.Width;
const int backHeight = intel_fb->Base.Height;
const int nbox = dPriv->numClipRects;
const drm_clip_rect_t *pbox = dPriv->pClipRects;
const int pitch = intelScreen->front.pitch / intelScreen->front.cpp;
#if 0
const int srcpitch = backRegion->pitch;
#endif
const int cpp = intelScreen->front.cpp;
int BR13, CMD;
int i;
const struct pipe_surface *backSurf;
const struct pipe_region *backRegion;
int srcpitch;
struct st_renderbuffer *strb;
/* blit from back color buffer if it exists, else front buffer */
strb = st_renderbuffer(intel_fb->Base.Attachment[BUFFER_BACK_LEFT].Renderbuffer);
if (strb) {
backSurf = strb->surface;
}
else {
strb = st_renderbuffer(intel_fb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
backSurf = strb->surface;
}
backRegion = backSurf->region;
srcpitch = backRegion->pitch;
const struct pipe_region *srcRegion = surf->region;
const int srcpitch= srcRegion->pitch;
ASSERT(intel_fb);
ASSERT(intel_fb->Base.Name == 0); /* Not a user-created FBO */
ASSERT(backRegion);
ASSERT(backRegion->cpp == cpp);
ASSERT(srcRegion);
ASSERT(srcRegion->cpp == cpp);
DBG(SWAP, "front pitch %d back pitch %d\n",
pitch, backRegion->pitch);
pitch, srcRegion->pitch);
if (cpp == 2) {
BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24);
@ -164,12 +157,15 @@ intelCopyBuffer(__DRIdrawablePrivate * dPriv,
if (pbox->x1 > pbox->x2 ||
pbox->y1 > pbox->y2 ||
pbox->x2 > intelScreen->front.width ||
pbox->y2 > intelScreen->front.height)
pbox->y2 > intelScreen->front.height) {
/* invalid cliprect, skip it */
continue;
}
box = *pbox;
if (rect) {
/* intersect cliprect with user-provided src rect */
drm_clip_rect_t rrect;
rrect.x1 = dPriv->x + rect->x1;
@ -212,7 +208,7 @@ intelCopyBuffer(__DRIdrawablePrivate * dPriv,
DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, 0);
OUT_BATCH((sbox.y1 << 16) | sbox.x1);
OUT_BATCH((srcpitch * cpp) & 0xffff);
OUT_RELOC(dri_bo(backRegion->buffer),
OUT_RELOC(dri_bo(srcRegion->buffer),
DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, 0);
@ -590,10 +586,13 @@ intelSwapBuffers(__DRIdrawablePrivate * dPriv)
_mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */
if (!intelScheduleSwap(dPriv, &missed_target)) {
struct pipe_surface *back_surf
= get_color_surface(intel_fb, BUFFER_BACK_LEFT);
driWaitForVBlank(dPriv, &intel_fb->vbl_seq, intel_fb->vblank_flags,
&missed_target);
intelCopyBuffer(dPriv, NULL);
intelDisplayBuffer(dPriv, back_surf, NULL);
}
intel_fb->swap_count++;
@ -621,6 +620,10 @@ intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h)
GLcontext *ctx = intel->st->ctx;
if (ctx->Visual.doubleBufferMode) {
struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
struct pipe_surface *back_surf
= get_color_surface(intel_fb, BUFFER_BACK_LEFT);
drm_clip_rect_t rect;
/* fixup cliprect (driDrawable may have changed?) later */
rect.x1 = x;
@ -628,7 +631,7 @@ intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h)
rect.x2 = w;
rect.y2 = h;
_mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */
intelCopyBuffer(dPriv, &rect);
intelDisplayBuffer(dPriv, back_surf, &rect);
}
}
else {

View file

@ -62,8 +62,9 @@ struct intel_framebuffer
};
void intelCopyBuffer(__DRIdrawablePrivate * dPriv,
const drm_clip_rect_t * rect);
extern void intelDisplayBuffer(__DRIdrawablePrivate * dPriv,
struct pipe_surface *surf,
const drm_clip_rect_t * rect);
extern void intel_wait_flips(struct intel_context *intel, GLuint batch_flags);

View file

@ -185,12 +185,13 @@ static void intel_wait_idle( struct pipe_winsys *sws )
* we copied its contents to the real frontbuffer. Our task is easy:
*/
static void
intel_flush_frontbuffer( struct pipe_winsys *sws )
intel_flush_frontbuffer( struct pipe_winsys *sws,
struct pipe_surface *surf )
{
struct intel_context *intel = intel_pipe_winsys(sws)->intel;
__DRIdrawablePrivate *dPriv = intel->driDrawable;
intelCopyBuffer(dPriv, NULL);
intelDisplayBuffer(dPriv, surf, NULL);
}

View file

@ -53,6 +53,7 @@ struct pipe_buffer_handle;
struct pipe_region;
struct pipe_surface;
/** Opaque type */
struct pipe_buffer_handle;
@ -63,7 +64,8 @@ struct pipe_winsys
* Do any special operations to ensure frontbuffer contents are
* displayed, eg copy fake frontbuffer.
*/
void (*flush_frontbuffer)( struct pipe_winsys *sws );
void (*flush_frontbuffer)( struct pipe_winsys *sws,
struct pipe_surface *surf );
/** Debug output */
void (*printf)( struct pipe_winsys *sws,

View file

@ -157,14 +157,14 @@ xm_buffer_get_subdata(struct pipe_winsys *pws, struct pipe_buffer_handle *buf,
}
static void
xm_flush_frontbuffer(struct pipe_winsys *pws)
xm_flush_frontbuffer(struct pipe_winsys *pws,
struct pipe_surface *surf )
{
/*
struct intel_context *intel = intel_pipe_winsys(sws)->intel;
__DRIdrawablePrivate *dPriv = intel->driDrawable;
intelCopyBuffer(dPriv, NULL);
*/
/* The Xlib driver's front color surfaces are actually X Windows so
* this flush is a no-op.
* If we instead did front buffer rendering to a temporary XImage,
* this would be the place to copy the Ximage to the on-screen Window.
*/
}
static void

View file

@ -35,6 +35,7 @@
#include "main/macros.h"
#include "st_context.h"
#include "st_cb_flush.h"
#include "st_cb_fbo.h"
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "pipe/p_winsys.h"
@ -59,9 +60,13 @@ static void st_flush(GLcontext *ctx)
if (st->flags.frontbuffer_dirty) {
struct st_renderbuffer *strb
= st_renderbuffer(ctx->DrawBuffer->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
struct pipe_surface *front_surf = strb->surface;
/* Hook for copying "fake" frontbuffer if necessary:
*/
st->pipe->winsys->flush_frontbuffer( st->pipe->winsys );
st->pipe->winsys->flush_frontbuffer( st->pipe->winsys, front_surf );
st->flags.frontbuffer_dirty = 0;
}
}