diff options
author | Keith Whitwell <keith@tungstengraphics.com> | 2005-02-07 16:56:02 +0000 |
---|---|---|
committer | Keith Whitwell <keith@tungstengraphics.com> | 2005-02-07 16:56:02 +0000 |
commit | 291082b4f8cc39cd7c455dbe28a2e271bdeac172 (patch) | |
tree | 441a6a1780e5a1a45ccf08172b39e1ee075193ab | |
parent | e780b1081f9a45b286abe3c059a0036a430c242f (diff) |
Get breadcrumb/fence code working correctly.
Use this widely in place of polling the engine status register.
Release textures according to this vs. their last usage.
Get texture swap-in/swap-out and aging working correctly.
-rw-r--r-- | src/mesa/drivers/dri/unichrome/via_context.c | 5 | ||||
-rw-r--r-- | src/mesa/drivers/dri/unichrome/via_context.h | 19 | ||||
-rw-r--r-- | src/mesa/drivers/dri/unichrome/via_fb.c | 130 | ||||
-rw-r--r-- | src/mesa/drivers/dri/unichrome/via_fb.h | 7 | ||||
-rw-r--r-- | src/mesa/drivers/dri/unichrome/via_ioctl.c | 151 | ||||
-rw-r--r-- | src/mesa/drivers/dri/unichrome/via_ioctl.h | 4 | ||||
-rw-r--r-- | src/mesa/drivers/dri/unichrome/via_span.c | 4 | ||||
-rw-r--r-- | src/mesa/drivers/dri/unichrome/via_tex.c | 215 | ||||
-rw-r--r-- | src/mesa/drivers/dri/unichrome/via_tex.h | 3 |
9 files changed, 364 insertions, 174 deletions
diff --git a/src/mesa/drivers/dri/unichrome/via_context.c b/src/mesa/drivers/dri/unichrome/via_context.c index 3308d371f2..6b0f73e753 100644 --- a/src/mesa/drivers/dri/unichrome/via_context.c +++ b/src/mesa/drivers/dri/unichrome/via_context.c @@ -289,6 +289,7 @@ static const struct dri_debug_control debug_control[] = { "sync", DEBUG_SYNC }, { "sleep", DEBUG_SLEEP }, { "pix", DEBUG_PIXEL }, + { "2d", DEBUG_2D }, { NULL, 0 } }; @@ -405,6 +406,10 @@ viaCreateContext(const __GLcontextModes *mesaVis, break; } + make_empty_list(&vmesa->freed_tex_buffers); + make_empty_list(&vmesa->tex_image_list[VIA_MEM_VIDEO]); + make_empty_list(&vmesa->tex_image_list[VIA_MEM_AGP]); + make_empty_list(&vmesa->tex_image_list[VIA_MEM_SYSTEM]); _mesa_init_driver_functions(&functions); viaInitTextureFuncs(&functions); diff --git a/src/mesa/drivers/dri/unichrome/via_context.h b/src/mesa/drivers/dri/unichrome/via_context.h index 1447be9cd6..7c4f5626ad 100644 --- a/src/mesa/drivers/dri/unichrome/via_context.h +++ b/src/mesa/drivers/dri/unichrome/via_context.h @@ -101,6 +101,7 @@ struct via_buffer { struct via_tex_buffer { struct via_tex_buffer *next, *prev; + struct via_texture_image *image; GLuint index; GLuint offset; GLuint size; @@ -114,7 +115,7 @@ struct via_tex_buffer { struct via_texture_image { struct gl_texture_image image; - struct via_tex_buffer texMem; + struct via_tex_buffer *texMem; GLint pitchLog2; }; @@ -137,10 +138,6 @@ struct via_texture_object { }; -struct via_work { - struct via_work *next; - void (*do_work)( struct via_context * ); -}; struct via_context { GLint refcount; @@ -327,15 +324,20 @@ struct via_context { GLuint pfCurrentOffset; GLboolean allowPageFlip; - struct via_work *work; + GLuint lastBreadcrumbRead; + GLuint lastBreadcrumbWrite; + GLuint lastSwap[2]; + GLuint lastDma; + + struct via_tex_buffer tex_image_list[VIA_MEM_SYSTEM+1]; + struct via_tex_buffer freed_tex_buffers; + }; #define VIA_CONTEXT(ctx) ((struct via_context *)(ctx->DriverCtx)) -#define GET_DISPATCH_AGE(vmesa) vmesa->sarea->lastDispatch -#define GET_ENQUEUE_AGE(vmesa) vmesa->sarea->lastEnqueue /* Lock the hardware and validate our state. @@ -372,6 +374,7 @@ extern GLuint VIA_DEBUG; #define DEBUG_SYNC 0x400 #define DEBUG_SLEEP 0x800 #define DEBUG_PIXEL 0x1000 +#define DEBUG_2D 0x2000 extern void viaGetLock(struct via_context *vmesa, GLuint flags); diff --git a/src/mesa/drivers/dri/unichrome/via_fb.c b/src/mesa/drivers/dri/unichrome/via_fb.c index d0c7a82d3b..35a19cd12c 100644 --- a/src/mesa/drivers/dri/unichrome/via_fb.c +++ b/src/mesa/drivers/dri/unichrome/via_fb.c @@ -29,6 +29,7 @@ #include "via_fb.h" #include "xf86drm.h" #include "imports.h" +#include "simple_list.h" #include <sys/ioctl.h> GLboolean @@ -96,9 +97,23 @@ via_free_dma_buffer(struct via_context *vmesa) vmesa->dma = 0; } -GLboolean -via_alloc_texture(struct via_context *vmesa, struct via_tex_buffer *t) + +/* These functions now allocate and free the via_tex_buffer struct as well: + */ +struct via_tex_buffer * +via_alloc_texture(struct via_context *vmesa, + GLuint size, + GLuint memType) { + struct via_tex_buffer *t = CALLOC_STRUCT(via_tex_buffer); + + if (!t) + goto cleanup; + + t->size = size; + t->memType = memType; + insert_at_tail(&vmesa->tex_image_list[memType], t); + if (t->memType == VIA_MEM_AGP || t->memType == VIA_MEM_VIDEO) { drm_via_mem_t fb; @@ -108,15 +123,11 @@ via_alloc_texture(struct via_context *vmesa, struct via_tex_buffer *t) fb.type = t->memType; if (ioctl(vmesa->driFd, DRM_IOCTL_VIA_ALLOCMEM, &fb) != 0 || - fb.index == 0) { - if (VIA_DEBUG & (DEBUG_IOCTL|DEBUG_TEXTURE)) - fprintf(stderr, "via_alloc_texture fail\n"); - t->index = 0; - return GL_FALSE; - } + fb.index == 0) + goto cleanup; if (0) - fprintf(stderr, "offset %x index %x\n", fb.offset, fb.index); + fprintf(stderr, "offset %lx index %lx\n", fb.offset, fb.index); t->offset = fb.offset; t->index = fb.index; @@ -130,44 +141,87 @@ via_alloc_texture(struct via_context *vmesa, struct via_tex_buffer *t) t->texBase = fb.offset; } - return GL_TRUE; + return t; } else if (t->memType == VIA_MEM_SYSTEM) { t->bufAddr = MESA_PBUFFER_ALLOC(t->size); - t->texBase = 0; - t->offset = 0; - t->index = 0; - - return t->bufAddr != NULL; + if (!t->bufAddr) + goto cleanup; + + return t; } - else - return GL_FALSE; + + cleanup: + if (t) { + remove_from_list(t); + FREE(t); + } + + return NULL; +} + + +static void +via_do_free_texture(struct via_context *vmesa, struct via_tex_buffer *t) +{ + drm_via_mem_t fb; + + remove_from_list( t ); + + fb.context = vmesa->hHWContext; + fb.index = t->index; + fb.type = t->memType; + + if (ioctl(vmesa->driFd, DRM_IOCTL_VIA_FREEMEM, &fb)) { + fprintf(stderr, "via_free_texture fail\n"); + } + + FREE(t); } +/* Release textures which were potentially still being referenced by + * hardware at the time when they were originally freed. + */ +void +via_release_pending_textures( struct via_context *vmesa ) +{ + struct via_tex_buffer *s, *tmp; + + foreach_s( s, tmp, &vmesa->freed_tex_buffers ) { + if (s->lastUsed <= vmesa->lastBreadcrumbRead) { + if (VIA_DEBUG & DEBUG_TEXTURE) + fprintf(stderr, "%s: release tex sz %d lastUsed %x\n",__FUNCTION__, s->size, s->lastUsed); + remove_from_list(s); + via_do_free_texture(vmesa, s); + } + } +} + + + void via_free_texture(struct via_context *vmesa, struct via_tex_buffer *t) { - if (t->memType == VIA_MEM_SYSTEM) { - MESA_PBUFFER_FREE(t->bufAddr); - t->bufAddr = 0; - } - else if (t->index) { - drm_via_mem_t fb; - - fb.context = vmesa->hHWContext; - fb.index = t->index; - fb.type = t->memType; - - if (ioctl(vmesa->driFd, DRM_IOCTL_VIA_FREEMEM, &fb)) { - fb.context = vmesa->hHWContext; - if (ioctl(vmesa->driFd, DRM_IOCTL_VIA_FREEMEM, &fb)) { - fprintf(stderr, "via_free_texture fail\n"); - } - } - - t->bufAddr = NULL; - t->index = 0; - } + if (!t) { + return; + } + else if (t->memType == VIA_MEM_SYSTEM) { + remove_from_list(t); + MESA_PBUFFER_FREE(t->bufAddr); + FREE(t); + } + else if (t->index && viaCheckBreadcrumb(vmesa, t->lastUsed)) { + remove_from_list(t); + via_do_free_texture( vmesa, t ); + } + else { + /* Close current breadcrumb so that we can free this eventually: + */ + if (t->lastUsed == vmesa->lastBreadcrumbWrite) + viaEmitBreadcrumb(vmesa); + + move_to_tail( &vmesa->freed_tex_buffers, t ); + } } diff --git a/src/mesa/drivers/dri/unichrome/via_fb.h b/src/mesa/drivers/dri/unichrome/via_fb.h index 3b3c0a1cac..7ee153f474 100644 --- a/src/mesa/drivers/dri/unichrome/via_fb.h +++ b/src/mesa/drivers/dri/unichrome/via_fb.h @@ -29,9 +29,14 @@ extern GLboolean via_alloc_draw_buffer(struct via_context *vmesa, struct via_buffer *buf); extern GLboolean via_alloc_dma_buffer(struct via_context *vmesa); -extern GLboolean via_alloc_texture(struct via_context *vmesa, struct via_tex_buffer *t); + +struct via_tex_buffer * +via_alloc_texture(struct via_context *vmesa, + GLuint size, + GLuint memType); extern void via_free_draw_buffer(struct via_context *vmesa, struct via_buffer *buf); extern void via_free_dma_buffer(struct via_context *vmesa); extern void via_free_texture(struct via_context *vmesa, struct via_tex_buffer *t); +void via_release_pending_textures( struct via_context *vmesa ); #endif diff --git a/src/mesa/drivers/dri/unichrome/via_ioctl.c b/src/mesa/drivers/dri/unichrome/via_ioctl.c index 3f179bc31b..6e94c6a9b9 100644 --- a/src/mesa/drivers/dri/unichrome/via_ioctl.c +++ b/src/mesa/drivers/dri/unichrome/via_ioctl.c @@ -35,6 +35,7 @@ #include "via_tris.h" #include "via_ioctl.h" #include "via_state.h" +#include "via_fb.h" #include "via_3d_reg.h" #include "vblank.h" @@ -117,7 +118,7 @@ static void viaBlit(struct via_context *vmesa, GLuint bpp, GLuint dwGEMode, srcX, dstX, cmd; RING_VARS; - if (VIA_DEBUG & DEBUG_IOCTL) + if (VIA_DEBUG & DEBUG_2D) fprintf(stderr, "%s bpp %d src %x/%x dst %x/%x w %d h %d mode: %x color: 0x%08x mask 0x%08x\n", __FUNCTION__, bpp, srcBase, srcPitch, dstBase, dstPitch, w,h, blitMode, color, nMask); @@ -237,7 +238,7 @@ static void viaClear(GLcontext *ctx, GLbitfield mask, GLboolean all, mask &= ~DD_STENCIL_BIT; } else { - if (VIA_DEBUG & DEBUG_IOCTL) + if (VIA_DEBUG & DEBUG_2D) fprintf(stderr, "XXX: Clear stencil writemask %x -- need triangles (or a ROP?)\n", ctx->Stencil.WriteMask[0]); } @@ -351,20 +352,20 @@ static void viaDoSwapBuffers(struct via_context *vmesa, w, h, VIA_BLIT_COPY, 0, 0); } + + viaFlushDmaLocked(vmesa, VIA_NO_CLIPRECTS); /* redundant */ } -static void viaEmitBreadcrumb( struct via_context *vmesa, GLuint value ) +static void viaEmitBreadcrumbLocked( struct via_context *vmesa ) { struct via_buffer *buffer = &vmesa->breadcrumb; + GLuint value = vmesa->lastBreadcrumbWrite + 1; - if (VIA_DEBUG & DEBUG_IOCTL) - fprintf(stderr, "emit %x offset %x pitch %x\n", value, buffer->offset, buffer->pitch); + if (VIA_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "%s %d\n", __FUNCTION__, value); - /* BUG: with this flush uncommented, the emit-breadcrumb blit - * has no effect: - */ -/* VIA_FLUSH_DMA(vmesa); */ + assert(!vmesa->dmaLow); viaBlit(vmesa, buffer->bpp, @@ -373,48 +374,75 @@ static void viaEmitBreadcrumb( struct via_context *vmesa, GLuint value ) 1, 1, VIA_BLIT_FILL, value, 0); - VIA_FLUSH_DMA(vmesa); + viaFlushDmaLocked(vmesa, VIA_NO_CLIPRECTS); /* often redundant */ + vmesa->lastBreadcrumbWrite = value; } - -static GLboolean viaReceivedBreadcrumb( struct via_context *vmesa ) +void viaEmitBreadcrumb( struct via_context *vmesa ) { - GLuint *buf = (GLuint *)vmesa->breadcrumb.map; - GLuint value; - - if (vmesa->vblank_flags == VBLANK_FLAG_SYNC || vmesa->swap_count == 0) - value = vmesa->swap_count; - else - value = vmesa->swap_count - 1; - - if (VIA_DEBUG & DEBUG_IOCTL) - fprintf(stderr, "want %x got %x, addr %p\n", value, *buf, buf); + LOCK_HARDWARE(vmesa); + if (vmesa->dmaLow) + viaFlushDmaLocked(vmesa, 0); - if (value <= *buf) - return GL_TRUE; + viaEmitBreadcrumbLocked( vmesa ); + UNLOCK_HARDWARE(vmesa); +} - if ((((GLuint)*vmesa->regEngineStatus) & 0xFFFEFFFF) == 0x00020000) { - if (VIA_DEBUG & DEBUG_IOCTL) - fprintf(stderr, "failsafe - engine is idle\n"); +static GLboolean viaCheckIdle( struct via_context *vmesa ) +{ + if ((vmesa->regEngineStatus[0] & 0xFFFEFFFF) == 0x00020000) { return GL_TRUE; } - return GL_FALSE; } -static GLboolean viaCheckIdle( struct via_context *vmesa ) + +GLboolean viaCheckBreadcrumb( struct via_context *vmesa, GLuint value ) +{ + GLuint *buf = (GLuint *)vmesa->breadcrumb.map; + vmesa->lastBreadcrumbRead = *buf; + + if (VIA_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "%s %d <= %d: %d\n", __FUNCTION__, value, vmesa->lastBreadcrumbRead, + value <= vmesa->lastBreadcrumbRead); + + return value <= vmesa->lastBreadcrumbRead; +} + +static void viaWaitBreadcrumb( struct via_context *vmesa, GLuint value ) { - return (vmesa->regEngineStatus[0] & 0xFFFEFFFF) == 0x00020000; + if (VIA_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "%s %d\n", __FUNCTION__, value); + + assert(value < vmesa->lastBreadcrumbWrite); + + while (!viaCheckBreadcrumb( vmesa, value )) { + viaSwapOutWork( vmesa ); + via_release_pending_textures( vmesa ); + } } void viaWaitIdle( struct via_context *vmesa ) { - while (!viaCheckIdle( vmesa )) { - if (vmesa->work) { - vmesa->work->do_work( vmesa ); - } + VIA_FLUSH_DMA(vmesa); + + if (VIA_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "%s lastDma %d lastBreadcrumbWrite %d\n", + __FUNCTION__, vmesa->lastDma, vmesa->lastBreadcrumbWrite); + + /* Need to emit a new breadcrumb? + */ + if (vmesa->lastDma == vmesa->lastBreadcrumbWrite) { + LOCK_HARDWARE(vmesa); + viaEmitBreadcrumbLocked( vmesa ); + UNLOCK_HARDWARE(vmesa); } + + /* Need to wait? + */ + if (vmesa->lastDma > vmesa->lastBreadcrumbRead) + viaWaitBreadcrumb( vmesa, vmesa->lastDma ); } @@ -423,18 +451,32 @@ void viaWaitIdle( struct via_context *vmesa ) * except that WAIT_IDLE() will spin the CPU polling, while this is * IRQ driven. */ -static void viaWaitIdleVBlank( const __DRIdrawablePrivate *dPriv, struct via_context *vmesa ) +static void viaWaitIdleVBlank( const __DRIdrawablePrivate *dPriv, + struct via_context *vmesa, + GLuint value ) { GLboolean missed_target; - viaEmitBreadcrumb(vmesa, vmesa->swap_count); + VIA_FLUSH_DMA(vmesa); + + if (vmesa->thrashing) + viaSwapOutWork(vmesa); + + if (!value) + return; - while (!viaReceivedBreadcrumb(vmesa)) { - if (vmesa->work) { - vmesa->work->do_work( vmesa ); + assert(value < vmesa->lastBreadcrumbWrite); + + if (value <= vmesa->lastBreadcrumbRead) + return; + + while (!viaCheckBreadcrumb(vmesa, value)) { + if (viaSwapOutWork(vmesa)) { + continue; } else if (vmesa->vblank_flags == VBLANK_FLAG_SYNC) { - driWaitForVBlank( dPriv, & vmesa->vbl_seq, vmesa->vblank_flags, & missed_target ); + driWaitForVBlank( dPriv, & vmesa->vbl_seq, + vmesa->vblank_flags, & missed_target ); if ( missed_target ) { vmesa->swap_missed_count++; vmesa->get_ust( &vmesa->swap_missed_ust ); @@ -443,7 +485,8 @@ static void viaWaitIdleVBlank( const __DRIdrawablePrivate *dPriv, struct via_con } vmesa->thrashing = 0; /* reset flag on swap */ - vmesa->swap_count++; + vmesa->swap_count++; + via_release_pending_textures( vmesa ); } @@ -452,7 +495,7 @@ static void viaDoPageFlipLocked(struct via_context *vmesa, GLuint offset) { RING_VARS; - if (VIA_DEBUG & DEBUG_IOCTL) + if (VIA_DEBUG & DEBUG_2D) fprintf(stderr, "%s %x\n", __FUNCTION__, offset); if (!vmesa->nDoneFirstFlip) { @@ -473,13 +516,14 @@ static void viaDoPageFlipLocked(struct via_context *vmesa, GLuint offset) ((offset & 0xFF000000) >> 24) | 0x0100); ADVANCE_RING(); - viaFlushDmaLocked(vmesa, VIA_NO_CLIPRECTS); vmesa->pfCurrentOffset = vmesa->sarea->pfCurrentOffset = offset; + + viaFlushDmaLocked(vmesa, VIA_NO_CLIPRECTS); /* often redundant */ } void viaResetPageFlippingLocked(struct via_context *vmesa) { - if (VIA_DEBUG & DEBUG_IOCTL) + if (VIA_DEBUG & DEBUG_2D) fprintf(stderr, "%s\n", __FUNCTION__); viaDoPageFlipLocked( vmesa, 0 ); @@ -503,7 +547,8 @@ void viaCopyBuffer(const __DRIdrawablePrivate *dPriv) { struct via_context *vmesa = (struct via_context *)dPriv->driContextPriv->driverPrivate; - viaWaitIdleVBlank(dPriv, vmesa); + VIA_FLUSH_DMA(vmesa); + viaWaitIdleVBlank(dPriv, vmesa, vmesa->lastSwap[1]); LOCK_HARDWARE(vmesa); @@ -512,14 +557,15 @@ void viaCopyBuffer(const __DRIdrawablePrivate *dPriv) */ if (dPriv->numClipRects && vmesa->sarea->pfCurrentOffset != 0) { viaResetPageFlippingLocked(vmesa); - UNLOCK_HARDWARE(vmesa); return; } - - viaDoSwapBuffers(vmesa, dPriv->pClipRects, dPriv->numClipRects); - viaFlushDmaLocked(vmesa, VIA_NO_CLIPRECTS); + viaDoSwapBuffers(vmesa, dPriv->pClipRects, dPriv->numClipRects); + vmesa->lastSwap[1] = vmesa->lastSwap[0]; + vmesa->lastSwap[0] = vmesa->lastBreadcrumbWrite; + viaEmitBreadcrumbLocked(vmesa); UNLOCK_HARDWARE(vmesa); + vmesa->get_ust( &vmesa->swap_ust ); } @@ -530,11 +576,15 @@ void viaPageFlip(const __DRIdrawablePrivate *dPriv) struct via_buffer buffer_tmp; VIA_FLUSH_DMA(vmesa); + viaWaitIdleVBlank(dPriv, vmesa, vmesa->lastSwap[0]); + LOCK_HARDWARE(vmesa); viaDoPageFlipLocked(vmesa, vmesa->back.offset); + vmesa->lastSwap[1] = vmesa->lastSwap[0]; + vmesa->lastSwap[0] = vmesa->lastBreadcrumbWrite; + viaEmitBreadcrumbLocked(vmesa); UNLOCK_HARDWARE(vmesa); - viaWaitIdleVBlank(dPriv, vmesa); vmesa->get_ust( &vmesa->swap_ust ); @@ -742,6 +792,7 @@ void viaFlushDmaLocked(struct via_context *vmesa, GLuint flags) __FUNCTION__, vmesa->dmaLow); } + vmesa->lastDma = vmesa->lastBreadcrumbWrite; if (VIA_DEBUG & DEBUG_DMA) dump_dma( vmesa ); diff --git a/src/mesa/drivers/dri/unichrome/via_ioctl.h b/src/mesa/drivers/dri/unichrome/via_ioctl.h index dfa20892d4..19df625b70 100644 --- a/src/mesa/drivers/dri/unichrome/via_ioctl.h +++ b/src/mesa/drivers/dri/unichrome/via_ioctl.h @@ -39,6 +39,10 @@ void viaCheckDma(struct via_context *vmesa, GLuint bytes); void viaResetPageFlippingLocked(struct via_context *vmesa); void viaWaitIdle(struct via_context *vmesa); +GLboolean viaCheckBreadcrumb( struct via_context *vmesa, GLuint value ); +void viaEmitBreadcrumb( struct via_context *vmesa ); + + #define VIA_FINISH_PRIM(vmesa) do { \ if (vmesa->dmaLastPrim) \ viaFinishPrimitive( vmesa ); \ diff --git a/src/mesa/drivers/dri/unichrome/via_span.c b/src/mesa/drivers/dri/unichrome/via_span.c index 6c33c6f03e..ba73cccb67 100644 --- a/src/mesa/drivers/dri/unichrome/via_span.c +++ b/src/mesa/drivers/dri/unichrome/via_span.c @@ -194,10 +194,8 @@ static void viaSetBuffer(GLcontext *ctx, GLframebuffer *colorBuffer, void viaSpanRenderStart( GLcontext *ctx ) { struct via_context *vmesa = VIA_CONTEXT(ctx); - VIA_FINISH_PRIM(vmesa); - LOCK_HARDWARE(vmesa); - viaFlushDmaLocked(vmesa, 0); viaWaitIdle(vmesa); + LOCK_HARDWARE(vmesa); } void viaSpanRenderFinish( GLcontext *ctx ) diff --git a/src/mesa/drivers/dri/unichrome/via_tex.c b/src/mesa/drivers/dri/unichrome/via_tex.c index c8a8e9b92f..97766c43f8 100644 --- a/src/mesa/drivers/dri/unichrome/via_tex.c +++ b/src/mesa/drivers/dri/unichrome/via_tex.c @@ -33,6 +33,7 @@ #include "colortab.h" #include "convolve.h" #include "context.h" +#include "simple_list.h" #include "texcompress.h" #include "texformat.h" #include "texobj.h" @@ -215,28 +216,25 @@ static const char *get_memtype_name( GLint memType ) } -static GLboolean viaMoveTexObject( struct via_context *vmesa, - struct via_texture_object *viaObj, - GLint newMemType ) +static GLboolean viaMoveTexBuffers( struct via_context *vmesa, + struct via_tex_buffer **buffers, + GLuint nr, + GLint newMemType ) { - struct via_texture_image **viaImage = - (struct via_texture_image **)&viaObj->obj.Image[0][0]; - - struct via_tex_buffer newTexBuf[VIA_MAX_TEXLEVELS]; + struct via_tex_buffer *newTexBuf[VIA_MAX_TEXLEVELS]; GLint i; if (VIA_DEBUG & DEBUG_TEXTURE) - fprintf(stderr, "%s, from %s to %s\n", + fprintf(stderr, "%s to %s\n", __FUNCTION__, - get_memtype_name(viaObj->memType), get_memtype_name(newMemType)); memset(newTexBuf, 0, sizeof(newTexBuf)); /* First do all the allocations (or fail): */ - for (i = viaObj->firstLevel; i <= viaObj->lastLevel; i++) { - if (viaImage[i]->texMem.memType != newMemType) { + for (i = 0; i < nr; i++) { + if (buffers[i]->memType != newMemType) { /* Don't allow uploads in a thrash state. Should try and * catch this earlier. @@ -244,9 +242,10 @@ static GLboolean viaMoveTexObject( struct via_context *vmesa, if (vmesa->thrashing && newMemType != VIA_MEM_SYSTEM) goto cleanup; - newTexBuf[i].size = viaImage[i]->texMem.size; - newTexBuf[i].memType = newMemType; - if (!via_alloc_texture(vmesa, &newTexBuf[i])) + newTexBuf[i] = via_alloc_texture(vmesa, + buffers[i]->size, + newMemType); + if (!newTexBuf[i]) goto cleanup; } } @@ -254,24 +253,24 @@ static GLboolean viaMoveTexObject( struct via_context *vmesa, /* Now copy all the image data and free the old texture memory. */ - for (i = viaObj->firstLevel; i <= viaObj->lastLevel; i++) { - if (viaImage[i]->texMem.memType != newMemType) { - memcpy(newTexBuf[i].bufAddr, - viaImage[i]->texMem.bufAddr, - viaImage[i]->texMem.size); - - via_free_texture(vmesa, &viaImage[i]->texMem); - viaImage[i]->texMem = newTexBuf[i]; - viaImage[i]->image.Data = viaImage[i]->texMem.bufAddr; - -/* move_to_head( &viaImage[i], &vmesa->image_list[newMemType] ); */ + for (i = 0; i < nr; i++) { + if (newTexBuf[i]) { + memcpy(newTexBuf[i]->bufAddr, + buffers[i]->bufAddr, + buffers[i]->size); + + newTexBuf[i]->image = buffers[i]->image; + newTexBuf[i]->image->texMem = newTexBuf[i]; + newTexBuf[i]->image->image.Data = newTexBuf[i]->bufAddr; + via_free_texture(vmesa, buffers[i]); + insert_at_head( newTexBuf[i], + &vmesa->tex_image_list[newMemType] ); } } if (VIA_DEBUG & DEBUG_TEXTURE) fprintf(stderr, "%s - success\n", __FUNCTION__); - viaObj->memType = newMemType; return GL_TRUE; cleanup: @@ -280,9 +279,9 @@ static GLboolean viaMoveTexObject( struct via_context *vmesa, if (VIA_DEBUG & DEBUG_TEXTURE) fprintf(stderr, "%s - failed\n", __FUNCTION__); - for (i = viaObj->firstLevel; i <= viaObj->lastLevel; i++) { - if (newTexBuf[i].index) { - via_free_texture(vmesa, &newTexBuf[i]); + for (i = 0; i < nr; i++) { + if (newTexBuf[i]) { + via_free_texture(vmesa, newTexBuf[i]); } } @@ -290,16 +289,34 @@ static GLboolean viaMoveTexObject( struct via_context *vmesa, } +static GLboolean viaMoveTexObject( struct via_context *vmesa, + struct via_texture_object *viaObj, + GLint newMemType ) +{ + struct via_texture_image **viaImage = + (struct via_texture_image **)&viaObj->obj.Image[0][0]; + struct via_tex_buffer *buffers[VIA_MAX_TEXLEVELS]; + GLuint i, nr = 0; + + for (i = viaObj->firstLevel; i <= viaObj->lastLevel; i++) + buffers[nr++] = viaImage[i]->texMem; + if (viaMoveTexBuffers( vmesa, &buffers[0], nr, newMemType )) { + viaObj->memType = newMemType; + return GL_TRUE; + } + + return GL_FALSE; +} + + +#if 0 static GLboolean viaSwapOutTexObject( struct via_context *vmesa, struct via_texture_object *viaObj ) { return viaMoveTexObject( vmesa, viaObj, VIA_MEM_SYSTEM ); } - - - - +#endif static GLboolean viaSwapInTexObject( struct via_context *vmesa, @@ -308,33 +325,74 @@ static GLboolean viaSwapInTexObject( struct via_context *vmesa, const struct via_texture_image *baseImage = (struct via_texture_image *)viaObj->obj.Image[0][viaObj->obj.BaseLevel]; - if (baseImage->texMem.memType != VIA_MEM_SYSTEM) - return viaMoveTexObject( vmesa, viaObj, baseImage->texMem.memType ); + if (VIA_DEBUG & DEBUG_TEXTURE) + fprintf(stderr, "%s\n", __FUNCTION__); + + if (baseImage->texMem->memType != VIA_MEM_SYSTEM) + return viaMoveTexObject( vmesa, viaObj, baseImage->texMem->memType ); return (viaMoveTexObject( vmesa, viaObj, VIA_MEM_AGP ) || viaMoveTexObject( vmesa, viaObj, VIA_MEM_VIDEO )); } -void viaSwapOutWork( struct via_context *vmesa, - GLboolean (*checkIdle)( struct via_context * )) -{ -/* for (i = VIA_MEM_VIDEO; i < VIA_MEM_AGP; i++) { */ -/* foreach_s( viaImage, ) */ -/* } */ -} - -/* Free any resources pending on values upto 'fence' +/* Speculatively move texture images which haven't been used in a + * while back to system memory. Do at most one image per call. + * + * TODO: only do this when texture memory is low. + * + * TODO: use dma. + * + * TODO: keep the fb/agp version hanging around and use the local + * version as backing store, so re-upload might be avoided. + * + * TODO: do this properly in the kernel... */ -void viaTexRetireFence( struct via_context *vmesa, - GLuint fence ) +GLboolean viaSwapOutWork( struct via_context *vmesa ) { -/* foreach_s(viaImage, tmp, vmesa->deleted_tex_image_queue) { */ - + struct via_tex_buffer *s, *tmp; + GLuint done = 0; + GLuint heap, target; + + if (VIA_DEBUG & DEBUG_TEXTURE) + fprintf(stderr, "%s\n", __FUNCTION__); + + if (vmesa->thrashing) + target = 64*1024*1024; + else + target = 64*1024; + for (heap = VIA_MEM_VIDEO; heap <= VIA_MEM_AGP; heap++) { + foreach_s( s, tmp, &vmesa->tex_image_list[heap] ) { + if (s->lastUsed < vmesa->lastSwap[1]) { + struct via_texture_object *viaObj = + (struct via_texture_object *) s->image->image.TexObject; + + if (VIA_DEBUG & DEBUG_TEXTURE) + fprintf(stderr, + "back copy tex sz %d, lastUsed %d lastSwap %d\n", + s->size, s->lastUsed, vmesa->lastSwap); + + done += s->size; + viaMoveTexBuffers( vmesa, &s, 1, VIA_MEM_SYSTEM ); + viaObj->memType = VIA_MEM_MIXED; + } + else { + if (VIA_DEBUG & DEBUG_TEXTURE) + fprintf(stderr, + "don't touch tex sz %d, lastUsed %d lastSwap %d\n", + s->size, s->lastUsed, vmesa->lastSwap); + } + + if (done > target) + return GL_TRUE; + } + } + return done != 0; } + /* Basically, just collect the image dimensions and addresses for each * image and update the texture object state accordingly. */ @@ -428,6 +486,7 @@ static GLboolean viaSetTexImages(GLcontext *ctx, if (viaObj->memType == VIA_MEM_MIXED || viaObj->memType == VIA_MEM_SYSTEM) { + fprintf(stderr, "swapin\n"); if (!viaSwapInTexObject(vmesa, viaObj)) { if (VIA_DEBUG & DEBUG_TEXTURE) if (!vmesa->thrashing) @@ -451,16 +510,20 @@ static GLboolean viaSetTexImages(GLcontext *ctx, h = viaImage->image.HeightLog2; p = viaImage->pitchLog2; - texBase = viaImage->texMem.texBase; + assert(viaImage->texMem->memType == viaObj->memType); + + texBase = viaImage->texMem->texBase; if (!texBase) { if (VIA_DEBUG & DEBUG_TEXTURE) - fprintf(stderr, "%s: no texBase[%d]\n", __FUNCTION__, i); + fprintf(stderr, "%s: no texBase[%d]\n", __FUNCTION__, i); return GL_FALSE; } /* Image has to remain resident until the coming fence is retired. */ -/* viaImage->lastUse = vmesa->currentFence; */ + move_to_head( viaImage->texMem, + &vmesa->tex_image_list[viaImage->texMem->memType] ); + viaImage->texMem->lastUsed = vmesa->lastBreadcrumbWrite; viaObj->regTexBaseAndPitch[i].baseL = (((HC_SubA_HTXnL0BasL + i) << 24) | @@ -556,6 +619,11 @@ static void viaTexImage(GLcontext *ctx, struct via_texture_image *viaImage = (struct via_texture_image *)texImage; int heaps[3], nheaps, i; + if (!is_empty_list(&vmesa->freed_tex_buffers)) { + viaCheckBreadcrumb(vmesa, 0); + via_release_pending_textures(vmesa); + } + if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) { _mesa_adjust_image_for_convolution(ctx, dims, &postConvWidth, &postConvHeight); @@ -600,8 +668,6 @@ static void viaTexImage(GLcontext *ctx, * TODO: make room in agp if this fails. * TODO: use fb ram for textures as well. */ - viaImage->texMem.size = sizeInBytes; - viaImage->texMem.memType = viaObj->memType; switch (viaObj->memType) { @@ -617,36 +683,44 @@ static void viaTexImage(GLcontext *ctx, heaps[1] = VIA_MEM_SYSTEM; nheaps = 2; break; - case VIA_MEM_SYSTEM: case VIA_MEM_MIXED: +/* for ( */ +/* break; */ + case VIA_MEM_SYSTEM: default: - heaps[1] = VIA_MEM_SYSTEM; + heaps[0] = VIA_MEM_SYSTEM; nheaps = 1; break; } - for (i = 0; i < nheaps; i++) { - viaImage->texMem.memType = heaps[i]; - if (via_alloc_texture(vmesa, &viaImage->texMem)) - break; + for (i = 0; i < nheaps && !viaImage->texMem; i++) { + if (VIA_DEBUG & DEBUG_TEXTURE) + fprintf(stderr, "try %s (obj %s)\n", get_memtype_name(heaps[i]), + get_memtype_name(viaObj->memType)); + viaImage->texMem = via_alloc_texture(vmesa, sizeInBytes, heaps[i]); } - texImage->Data = viaImage->texMem.bufAddr; - if (!texImage->Data) { + if (!viaImage->texMem) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage"); return; } + if (viaImage->texMem->memType == VIA_MEM_SYSTEM) + fprintf(stderr, "upload to VIA_MEM_SYSTEM!\n"); + + viaImage->texMem->image = viaImage; + texImage->Data = viaImage->texMem->bufAddr; + if (viaObj->memType == VIA_MEM_UNKNOWN) - viaObj->memType = viaImage->texMem.memType; - else if (viaObj->memType != viaImage->texMem.memType) + viaObj->memType = viaImage->texMem->memType; + else if (viaObj->memType != viaImage->texMem->memType) viaObj->memType = VIA_MEM_MIXED; if (VIA_DEBUG & DEBUG_TEXTURE) fprintf(stderr, "%s, obj %s, image : %s\n", __FUNCTION__, get_memtype_name(viaObj->memType), - get_memtype_name(viaImage->texMem.memType)); + get_memtype_name(viaImage->texMem->memType)); vmesa->clearTexCache = 1; @@ -804,16 +878,9 @@ static void viaFreeTextureImageData( GLcontext *ctx, struct via_context *vmesa = VIA_CONTEXT(ctx); struct via_texture_image *image = (struct via_texture_image *)texImage; - if (image->texMem.index) { - /* Actually just doing a flush here isn't enough to ensure - * synchronization - need to make sure that any outstanding - * drawing with this texture has completed. - */ - VIA_FLUSH_DMA(vmesa); - via_free_texture(vmesa, &image->texMem); - } - else if (texImage->Data && !texImage->IsClientData) { - MESA_PBUFFER_FREE( texImage->Data ); + if (image->texMem) { + via_free_texture(vmesa, image->texMem); + image->texMem = NULL; } texImage->Data = NULL; diff --git a/src/mesa/drivers/dri/unichrome/via_tex.h b/src/mesa/drivers/dri/unichrome/via_tex.h index b46a764ef2..f6c024e438 100644 --- a/src/mesa/drivers/dri/unichrome/via_tex.h +++ b/src/mesa/drivers/dri/unichrome/via_tex.h @@ -28,7 +28,10 @@ #include "mtypes.h" +struct via_context; + GLboolean viaUpdateTextureState(GLcontext *ctx); void viaInitTextureFuncs(struct dd_function_table * functions); +GLboolean viaSwapOutWork( struct via_context *vmesa ); #endif |