r200_cmdbuf.c \
r200_pixel.c \
r200_tex.c \
- r200_texmem.c \
r200_texstate.c \
r200_tcl.c \
r200_swtcl.c \
}
- if (!rmesa->radeon.radeonScreen->kernel_mm)
- rmesa->dma.buf0_address = rmesa->radeon.radeonScreen->buffers->list[0].address;
-
(void) memset( rmesa->radeon.texture_heaps, 0, sizeof( rmesa->radeon.texture_heaps ) );
make_empty_list( & rmesa->radeon.swapped );
r200DestroySwtcl( rmesa->radeon.glCtx );
r200ReleaseArrays( rmesa->radeon.glCtx, ~0 );
- if (rmesa->dma.current.buf) {
- // r200ReleaseDmaRegion( rmesa, &rmesa->dma.current, __FUNCTION__ );
+ if (rmesa->dma.current) {
+ radeonReleaseDmaRegion(rmesa);
rcommonFlushCmdBuf( &rmesa->radeon, __FUNCTION__ );
}
GLuint envneeded;
};
-#define GET_START(rvb) (rmesa->radeon.radeonScreen->gart_buffer_offset + \
- (rvb)->address - rmesa->dma.buf0_address + \
- (rvb)->start)
-
#define R200_CMD_BUF_SZ (16*1024)
#define R200_ELT_BUF_SZ (16*1024)
#include "r200_maos.h"
#include "r200_tcl.h"
-
-#if 0
-/* Usage:
- * - from r200_tcl_render
- * - call r200EmitArrays to ensure uptodate arrays in dma
- * - emit primitives (new type?) which reference the data
- * -- need to use elts for lineloop, quads, quadstrip/flat
- * -- other primitives are all well-formed (need tristrip-1,fake-poly)
- *
- */
-static void emit_ubyte_rgba3( GLcontext *ctx,
- struct radeon_dma_region *rvb,
- char *data,
- int stride,
- int count )
-{
- int i;
- r200_color_t *out = (r200_color_t *)(rvb->start + rvb->address);
-
- if (R200_DEBUG & DEBUG_VERTS)
- fprintf(stderr, "%s count %d stride %d out %p\n",
- __FUNCTION__, count, stride, (void *)out);
-
- for (i = 0; i < count; i++) {
- out->red = *data;
- out->green = *(data+1);
- out->blue = *(data+2);
- out->alpha = 0xFF;
- out++;
- data += stride;
- }
-}
-
-static void emit_ubyte_rgba4( GLcontext *ctx,
- struct radeon_dma_region *rvb,
- char *data,
- int stride,
- int count )
-{
- int i;
- int *out = (int *)(rvb->address + rvb->start);
-
- if (R200_DEBUG & DEBUG_VERTS)
- fprintf(stderr, "%s count %d stride %d\n",
- __FUNCTION__, count, stride);
-
- if (stride == 4) {
- for (i = 0; i < count; i++)
- ((int *)out)[i] = LE32_TO_CPU(((int *)data)[i]);
- } else {
- for (i = 0; i < count; i++) {
- *(int *)out++ = LE32_TO_CPU(*(int *)data);
- data += stride;
- }
- }
-}
-
-
-static void emit_ubyte_rgba( GLcontext *ctx,
- struct radeon_dma_region *rvb,
- char *data,
- int size,
- int stride,
- int count )
-{
- r200ContextPtr rmesa = R200_CONTEXT(ctx);
-
- if (R200_DEBUG & DEBUG_VERTS)
- fprintf(stderr, "%s %d/%d\n", __FUNCTION__, count, size);
-
- assert (!rvb->buf);
-
- if (stride == 0) {
- // r200AllocDmaRegion( rmesa, rvb, 4, 4 );
- count = 1;
- rvb->aos_start = GET_START(rvb);
- rvb->aos_stride = 0;
- rvb->aos_size = 1;
- }
- else {
- // r200AllocDmaRegion( rmesa, rvb, 4 * count, 4 ); /* alignment? */
- rvb->aos_start = GET_START(rvb);
- rvb->aos_stride = 1;
- rvb->aos_size = 1;
- }
-
- /* Emit the data
- */
- switch (size) {
- case 3:
- emit_ubyte_rgba3( ctx, rvb, data, stride, count );
- break;
- case 4:
- emit_ubyte_rgba4( ctx, rvb, data, stride, count );
- break;
- default:
- assert(0);
- exit(1);
- break;
- }
-}
-#endif
-
-
#if defined(USE_X86_ASM)
#define COPY_DWORDS( dst, src, nr ) \
do { \
+++ /dev/null
-/**************************************************************************
-
-Copyright (C) Tungsten Graphics 2002. All Rights Reserved.
-The Weather Channel, Inc. funded Tungsten Graphics to develop the
-initial release of the Radeon 8500 driver under the XFree86
-license. This notice must be preserved.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation on the rights to use, copy, modify, merge, publish,
-distribute, sub license, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice (including the
-next paragraph) shall be included in all copies or substantial
-portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR THEIR
-SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
-IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-**************************************************************************/
-
-/*
- * Authors:
- * Kevin E. Martin <martin@valinux.com>
- * Gareth Hughes <gareth@valinux.com>
- *
- */
-
-#include <errno.h>
-
-#include "main/glheader.h"
-#include "main/imports.h"
-#include "main/context.h"
-#include "main/colormac.h"
-#include "main/macros.h"
-#include "r200_context.h"
-#include "r200_ioctl.h"
-#include "r200_tex.h"
-#include "radeon_reg.h"
-
-#include <unistd.h> /* for usleep() */
-
-#if 0
-/**
- * Destroy any device-dependent state associated with the texture. This may
- * include NULLing out hardware state that points to the texture.
- */
-void
-r200DestroyTexObj( r200ContextPtr rmesa, radeonTexObjPtr t )
-{
- if ( R200_DEBUG & DEBUG_TEXTURE ) {
- fprintf( stderr, "%s( %p, %p )\n", __FUNCTION__,
- (void *)t, (void *)t->base.tObj );
- }
-
- if ( rmesa != NULL ) {
- unsigned i;
-
-
- for ( i = 0 ; i < rmesa->radeon.glCtx->Const.MaxTextureUnits ; i++ ) {
- if ( t == rmesa->state.texture.unit[i].texobj ) {
- rmesa->state.texture.unit[i].texobj = NULL;
- rmesa->hw.tex[i].dirty = GL_FALSE;
- rmesa->hw.cube[i].dirty = GL_FALSE;
- }
- }
- }
-}
-
-
-/* ------------------------------------------------------------
- * Texture image conversions
- */
-
-
-static void r200UploadGARTClientSubImage( r200ContextPtr rmesa,
- radeonTexObjPtr t,
- struct gl_texture_image *texImage,
- GLint hwlevel,
- GLint x, GLint y,
- GLint width, GLint height )
-{
- const struct gl_texture_format *texFormat = texImage->TexFormat;
- GLuint srcPitch, dstPitch;
- int blit_format;
- int srcOffset;
-
- /*
- * XXX it appears that we always upload the full image, not a subimage.
- * I.e. x==0, y==0, width=texWidth, height=texWidth. If this is ever
- * changed, the src pitch will have to change.
- */
- switch ( texFormat->TexelBytes ) {
- case 1:
- blit_format = R200_CP_COLOR_FORMAT_CI8;
- srcPitch = t->image[0][0].width * texFormat->TexelBytes;
- dstPitch = t->image[0][0].width * texFormat->TexelBytes;
- break;
- case 2:
- blit_format = R200_CP_COLOR_FORMAT_RGB565;
- srcPitch = t->image[0][0].width * texFormat->TexelBytes;
- dstPitch = t->image[0][0].width * texFormat->TexelBytes;
- break;
- case 4:
- blit_format = R200_CP_COLOR_FORMAT_ARGB8888;
- srcPitch = t->image[0][0].width * texFormat->TexelBytes;
- dstPitch = t->image[0][0].width * texFormat->TexelBytes;
- break;
- default:
- return;
- }
-
- t->image[0][hwlevel].data = texImage->Data;
- srcOffset = r200GartOffsetFromVirtual( rmesa, texImage->Data );
-
- assert( srcOffset != ~0 );
-
- /* Don't currently need to cope with small pitches?
- */
- width = texImage->Width;
- height = texImage->Height;
-
- r200EmitWait( rmesa, RADEON_WAIT_3D );
-
- r200EmitBlit( rmesa, blit_format,
- srcPitch,
- srcOffset,
- dstPitch,
- t->bufAddr,
- x,
- y,
- t->image[0][hwlevel].x + x,
- t->image[0][hwlevel].y + y,
- width,
- height );
-
- r200EmitWait( rmesa, RADEON_WAIT_2D );
-}
-
-static void r200UploadRectSubImage( r200ContextPtr rmesa,
- radeonTexObjPtr t,
- struct gl_texture_image *texImage,
- GLint x, GLint y,
- GLint width, GLint height )
-{
- const struct gl_texture_format *texFormat = texImage->TexFormat;
- int blit_format, dstPitch, done;
-
- switch ( texFormat->TexelBytes ) {
- case 1:
- blit_format = R200_CP_COLOR_FORMAT_CI8;
- break;
- case 2:
- blit_format = R200_CP_COLOR_FORMAT_RGB565;
- break;
- case 4:
- blit_format = R200_CP_COLOR_FORMAT_ARGB8888;
- break;
- default:
- return;
- }
-
- t->image[0][0].data = texImage->Data;
-
- /* Currently don't need to cope with small pitches.
- */
- width = texImage->Width;
- height = texImage->Height;
- dstPitch = t->pp_txpitch + 32;
-
- if (rmesa->prefer_gart_client_texturing && texImage->IsClientData) {
- /* In this case, could also use GART texturing. This is
- * currently disabled, but has been tested & works.
- */
- if ( !t->image_override )
- t->pp_txoffset = r200GartOffsetFromVirtual( rmesa, texImage->Data );
- t->pp_txpitch = texImage->RowStride * texFormat->TexelBytes - 32;
-
- if (R200_DEBUG & DEBUG_TEXTURE)
- fprintf(stderr,
- "Using GART texturing for rectangular client texture\n");
-
- /* Release FB memory allocated for this image:
- */
- /* FIXME This may not be correct as driSwapOutTextureObject sets
- * FIXME dirty_images. It may be fine, though.
- */
- if ( t->base.memBlock ) {
- driSwapOutTextureObject( (driTextureObject *) t );
- }
- }
- else if (texImage->IsClientData) {
- /* Data already in GART memory, with usable pitch.
- */
- GLuint srcPitch;
- srcPitch = texImage->RowStride * texFormat->TexelBytes;
- r200EmitBlit( rmesa,
- blit_format,
- srcPitch,
- r200GartOffsetFromVirtual( rmesa, texImage->Data ),
- dstPitch, t->bufAddr,
- 0, 0,
- 0, 0,
- width, height );
- }
- else {
- /* Data not in GART memory, or bad pitch.
- */
- for (done = 0; done < height ; ) {
- struct radeon_dma_region region;
- int lines = MIN2( height - done, RADEON_BUFFER_SIZE / dstPitch );
- int src_pitch;
- char *tex;
-
- src_pitch = texImage->RowStride * texFormat->TexelBytes;
-
- tex = (char *)texImage->Data + done * src_pitch;
-
- memset(®ion, 0, sizeof(region));
- // r200AllocDmaRegion( rmesa, ®ion, lines * dstPitch, 1024 );
-
- /* Copy texdata to dma:
- */
- if (0)
- fprintf(stderr, "%s: src_pitch %d dst_pitch %d\n",
- __FUNCTION__, src_pitch, dstPitch);
-
- if (src_pitch == dstPitch) {
- memcpy( region.address + region.start, tex, lines * src_pitch );
- }
- else {
- char *buf = region.address + region.start;
- int i;
- for (i = 0 ; i < lines ; i++) {
- memcpy( buf, tex, src_pitch );
- buf += dstPitch;
- tex += src_pitch;
- }
- }
-
- r200EmitWait( rmesa, RADEON_WAIT_3D );
-
- /* Blit to framebuffer
- */
- r200EmitBlit( rmesa,
- blit_format,
- dstPitch, GET_START( ®ion ),
- dstPitch | (t->tile_bits >> 16),
- t->bufAddr,
- 0, 0,
- 0, done,
- width, lines );
-
- r200EmitWait( rmesa, RADEON_WAIT_2D );
-
- // r200ReleaseDmaRegion( rmesa, ®ion, __FUNCTION__ );
- done += lines;
- }
- }
-}
-
-
-/**
- * Upload the texture image associated with texture \a t at the specified
- * level at the address relative to \a start.
- */
-static void uploadSubImage( r200ContextPtr rmesa, radeonTexObjPtr t,
- GLint hwlevel,
- GLint x, GLint y, GLint width, GLint height,
- GLuint face )
-{
- struct gl_texture_image *texImage = NULL;
- GLuint offset;
- GLint imageWidth, imageHeight;
- GLint ret;
- drm_radeon_texture_t tex;
- drm_radeon_tex_image_t tmp;
- const int level = hwlevel + t->base.firstLevel;
-
- if ( R200_DEBUG & DEBUG_TEXTURE ) {
- fprintf( stderr, "%s( %p, %p ) level/width/height/face = %d/%d/%d/%u\n",
- __FUNCTION__, (void *)t, (void *)t->base.tObj,
- level, width, height, face );
- }
-
- ASSERT(face < 6);
-
- /* Ensure we have a valid texture to upload */
- if ( ( hwlevel < 0 ) || ( hwlevel >= RADEON_MAX_TEXTURE_LEVELS ) ) {
- _mesa_problem(NULL, "bad texture level in %s", __FUNCTION__);
- return;
- }
-
- texImage = t->base.tObj->Image[face][level];
-
- if ( !texImage ) {
- if ( R200_DEBUG & DEBUG_TEXTURE )
- fprintf( stderr, "%s: texImage %d is NULL!\n", __FUNCTION__, level );
- return;
- }
- if ( !texImage->Data ) {
- if ( R200_DEBUG & DEBUG_TEXTURE )
- fprintf( stderr, "%s: image data is NULL!\n", __FUNCTION__ );
- return;
- }
-
-
- if (t->base.tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
- assert(level == 0);
- assert(hwlevel == 0);
- if ( R200_DEBUG & DEBUG_TEXTURE )
- fprintf( stderr, "%s: image data is rectangular\n", __FUNCTION__);
- r200UploadRectSubImage( rmesa, t, texImage, x, y, width, height );
- return;
- }
- else if (texImage->IsClientData) {
- if ( R200_DEBUG & DEBUG_TEXTURE )
- fprintf( stderr, "%s: image data is in GART client storage\n",
- __FUNCTION__);
- r200UploadGARTClientSubImage( rmesa, t, texImage, hwlevel,
- x, y, width, height );
- return;
- }
- else if ( R200_DEBUG & DEBUG_TEXTURE )
- fprintf( stderr, "%s: image data is in normal memory\n",
- __FUNCTION__);
-
-
- imageWidth = texImage->Width;
- imageHeight = texImage->Height;
-
- offset = t->bufAddr + t->base.totalSize / 6 * face;
-
- if ( R200_DEBUG & (DEBUG_TEXTURE|DEBUG_IOCTL) ) {
- GLint imageX = 0;
- GLint imageY = 0;
- GLint blitX = t->image[face][hwlevel].x;
- GLint blitY = t->image[face][hwlevel].y;
- GLint blitWidth = t->image[face][hwlevel].width;
- GLint blitHeight = t->image[face][hwlevel].height;
- fprintf( stderr, " upload image: %d,%d at %d,%d\n",
- imageWidth, imageHeight, imageX, imageY );
- fprintf( stderr, " upload blit: %d,%d at %d,%d\n",
- blitWidth, blitHeight, blitX, blitY );
- fprintf( stderr, " blit ofs: 0x%07x level: %d/%d\n",
- (GLuint)offset, hwlevel, level );
- }
-
- t->image[face][hwlevel].data = texImage->Data;
-
- /* Init the DRM_RADEON_TEXTURE command / drm_radeon_texture_t struct.
- * NOTE: we're always use a 1KB-wide blit and I8 texture format.
- * We used to use 1, 2 and 4-byte texels and used to use the texture
- * width to dictate the blit width - but that won't work for compressed
- * textures. (Brian)
- * NOTE: can't do that with texture tiling. (sroland)
- */
- tex.offset = offset;
- tex.image = &tmp;
- /* copy (x,y,width,height,data) */
- memcpy( &tmp, &t->image[face][hwlevel], sizeof(tmp) );
-
- if (texImage->TexFormat->TexelBytes) {
- /* use multi-byte upload scheme */
- tex.height = imageHeight;
- tex.width = imageWidth;
- tex.format = t->pp_txformat & R200_TXFORMAT_FORMAT_MASK;
- if (tex.format == R200_TXFORMAT_ABGR8888) {
- /* drm will refuse abgr8888 textures. */
- tex.format = R200_TXFORMAT_ARGB8888;
- }
- tex.pitch = MAX2((texImage->Width * texImage->TexFormat->TexelBytes) / 64, 1);
- tex.offset += tmp.x & ~1023;
- tmp.x = tmp.x % 1024;
- if (t->tile_bits & R200_TXO_MICRO_TILE) {
- /* need something like "tiled coordinates" ? */
- tmp.y = tmp.x / (tex.pitch * 128) * 2;
- tmp.x = tmp.x % (tex.pitch * 128) / 2 / texImage->TexFormat->TexelBytes;
- tex.pitch |= RADEON_DST_TILE_MICRO >> 22;
- }
- else {
- tmp.x = tmp.x >> (texImage->TexFormat->TexelBytes >> 1);
- }
- if ((t->tile_bits & R200_TXO_MACRO_TILE) &&
- (texImage->Width * texImage->TexFormat->TexelBytes >= 256) &&
- ((!(t->tile_bits & R200_TXO_MICRO_TILE) && (texImage->Height >= 8)) ||
- (texImage->Height >= 16))) {
- /* weird: R200 disables macro tiling if mip width is smaller than 256 bytes,
- OR if height is smaller than 8 automatically, but if micro tiling is active
- the limit is height 16 instead ? */
- tex.pitch |= RADEON_DST_TILE_MACRO >> 22;
- }
- }
- else {
- /* In case of for instance 8x8 texture (2x2 dxt blocks), padding after the first two blocks is
- needed (only with dxt1 since 2 dxt3/dxt5 blocks already use 32 Byte). */
- /* set tex.height to 1/4 since 1 "macropixel" (dxt-block) has 4 real pixels. Needed
- so the kernel module reads the right amount of data. */
- tex.format = R200_TXFORMAT_I8; /* any 1-byte texel format */
- tex.pitch = (BLIT_WIDTH_BYTES / 64);
- tex.height = (imageHeight + 3) / 4;
- tex.width = (imageWidth + 3) / 4;
- switch (t->pp_txformat & R200_TXFORMAT_FORMAT_MASK) {
- case R200_TXFORMAT_DXT1:
- tex.width *= 8;
- break;
- case R200_TXFORMAT_DXT23:
- case R200_TXFORMAT_DXT45:
- tex.width *= 16;
- break;
- default:
- fprintf(stderr, "unknown compressed tex format in uploadSubImage\n");
- }
- }
-
- LOCK_HARDWARE( &rmesa->radeon );
- do {
- ret = drmCommandWriteRead( rmesa->radeon.dri.fd, DRM_RADEON_TEXTURE,
- &tex, sizeof(drm_radeon_texture_t) );
- if (ret) {
- if (R200_DEBUG & DEBUG_IOCTL)
- fprintf(stderr, "DRM_RADEON_TEXTURE: again!\n");
- usleep(1);
- }
- } while ( ret == -EAGAIN );
-
- UNLOCK_HARDWARE( &rmesa->radeon );
-
- if ( ret ) {
- fprintf( stderr, "DRM_RADEON_TEXTURE: return = %d\n", ret );
- fprintf( stderr, " offset=0x%08x\n",
- offset );
- fprintf( stderr, " image width=%d height=%d\n",
- imageWidth, imageHeight );
- fprintf( stderr, " blit width=%d height=%d data=%p\n",
- t->image[face][hwlevel].width, t->image[face][hwlevel].height,
- t->image[face][hwlevel].data );
- exit( 1 );
- }
-}
-
-
-/**
- * Upload the texture images associated with texture \a t. This might
- * require the allocation of texture memory.
- *
- * \param rmesa Context pointer
- * \param t Texture to be uploaded
- * \param face Cube map face to be uploaded. Zero for non-cube maps.
- */
-
-int r200UploadTexImages( r200ContextPtr rmesa, radeonTexObjPtr t, GLuint face )
-{
- const int numLevels = t->base.lastLevel - t->base.firstLevel + 1;
-
- if ( R200_DEBUG & (DEBUG_TEXTURE|DEBUG_IOCTL) ) {
- fprintf( stderr, "%s( %p, %p ) sz=%d lvls=%d-%d\n", __FUNCTION__,
- (void *)rmesa->radeon.glCtx, (void *)t->base.tObj, t->base.totalSize,
- t->base.firstLevel, t->base.lastLevel );
- }
-
- if ( !t || t->base.totalSize == 0 || t->image_override )
- return 0;
-
- if (R200_DEBUG & DEBUG_SYNC) {
- fprintf(stderr, "%s: Syncing\n", __FUNCTION__ );
- r200Finish( rmesa->radeon.glCtx );
- }
-
- LOCK_HARDWARE( &rmesa->radeon );
-
- if ( t->base.memBlock == NULL ) {
- int heap;
-
- heap = driAllocateTexture( rmesa->radeon.texture_heaps, rmesa->radeon.nr_heaps,
- (driTextureObject *) t );
- if ( heap == -1 ) {
- UNLOCK_HARDWARE( &rmesa->radeon );
- return -1;
- }
-
- /* Set the base offset of the texture image */
- t->bufAddr = rmesa->radeon.radeonScreen->texOffset[heap]
- + t->base.memBlock->ofs;
- t->pp_txoffset = t->bufAddr;
-
- if (!(t->base.tObj->Image[0][0]->IsClientData)) {
- /* hope it's safe to add that here... */
- t->pp_txoffset |= t->tile_bits;
- }
-
- /* Mark this texobj as dirty on all units:
- */
- t->dirty_state = R200_TEX_ALL;
- }
-
- /* Let the world know we've used this memory recently.
- */
- driUpdateTextureLRU( (driTextureObject *) t );
- UNLOCK_HARDWARE( &rmesa->radeon );
-
- /* Upload any images that are new */
- if (t->base.dirty_images[face]) {
- int i;
- for ( i = 0 ; i < numLevels ; i++ ) {
- if ( (t->base.dirty_images[face] & (1 << (i+t->base.firstLevel))) != 0 ) {
- uploadSubImage( rmesa, t, i, 0, 0, t->image[face][i].width,
- t->image[face][i].height, face );
- }
- }
- t->base.dirty_images[face] = 0;
- }
-
-
- if (R200_DEBUG & DEBUG_SYNC) {
- fprintf(stderr, "%s: Syncing\n", __FUNCTION__ );
- r200Finish( rmesa->radeon.glCtx );
- }
-
- return 0;
-}
-#endif
radeon->vtbl.update_draw_buffer = r300UpdateDrawBuffer;
radeon->vtbl.emit_cs_header = r300_vtbl_emit_cs_header;
radeon->vtbl.emit_state = r300_vtbl_emit_state;
+ radeon->vtbl.flush_vertices = r300_vtbl_flush_vertices;
}
GLuint specoffset;
struct radeon_bo *bo;
- void (*flush) (r300ContextPtr);
};
}
/* Setup INPUT_ROUTE. */
- if (rmesa->radeon.radeonScreen->kernel_mm) {
- R300_STATECHANGE(rmesa, vir[0]);
- rmesa->hw.vir[0].cmd[0] &= 0xC000FFFF;
- rmesa->hw.vir[1].cmd[0] &= 0xC000FFFF;
- rmesa->hw.vir[0].cmd[0] |=
- (r300VAPInputRoute0(&rmesa->hw.vir[0].cmd[R300_VIR_CNTL_0],
- vb->AttribPtr, inputs, tab, nr) & 0x3FFF) << 16;
- R300_STATECHANGE(rmesa, vir[1]);
- rmesa->hw.vir[1].cmd[0] |=
- (r300VAPInputRoute1(&rmesa->hw.vir[1].cmd[R300_VIR_CNTL_0], swizzle,
- nr) & 0x3FFF) << 16;
- } else {
- R300_STATECHANGE(rmesa, vir[0]);
- ((drm_r300_cmd_header_t *) rmesa->hw.vir[0].cmd)->packet0.count =
- r300VAPInputRoute0(&rmesa->hw.vir[0].cmd[R300_VIR_CNTL_0],
- vb->AttribPtr, inputs, tab, nr);
- R300_STATECHANGE(rmesa, vir[1]);
- ((drm_r300_cmd_header_t *) rmesa->hw.vir[1].cmd)->packet0.count =
- r300VAPInputRoute1(&rmesa->hw.vir[1].cmd[R300_VIR_CNTL_0], swizzle,
- nr);
- }
-
+ if (rmesa->radeon.radeonScreen->kernel_mm) {
+ R300_STATECHANGE(rmesa, vir[0]);
+ rmesa->hw.vir[0].cmd[0] &= 0xC000FFFF;
+ rmesa->hw.vir[1].cmd[0] &= 0xC000FFFF;
+ rmesa->hw.vir[0].cmd[0] |=
+ (r300VAPInputRoute0(&rmesa->hw.vir[0].cmd[R300_VIR_CNTL_0],
+ vb->AttribPtr, inputs, tab, nr) & 0x3FFF) << 16;
+ R300_STATECHANGE(rmesa, vir[1]);
+ rmesa->hw.vir[1].cmd[0] |=
+ (r300VAPInputRoute1(&rmesa->hw.vir[1].cmd[R300_VIR_CNTL_0], swizzle,
+ nr) & 0x3FFF) << 16;
+ } else {
+ R300_STATECHANGE(rmesa, vir[0]);
+ ((drm_r300_cmd_header_t *) rmesa->hw.vir[0].cmd)->packet0.count =
+ r300VAPInputRoute0(&rmesa->hw.vir[0].cmd[R300_VIR_CNTL_0],
+ vb->AttribPtr, inputs, tab, nr);
+ R300_STATECHANGE(rmesa, vir[1]);
+ ((drm_r300_cmd_header_t *) rmesa->hw.vir[1].cmd)->packet0.count =
+ r300VAPInputRoute1(&rmesa->hw.vir[1].cmd[R300_VIR_CNTL_0], swizzle,
+ nr);
+ }
+
/* Setup INPUT_CNTL. */
R300_STATECHANGE(rmesa, vic);
rmesa->hw.vic.cmd[R300_VIC_CNTL_0] = r300VAPInputCntl0(ctx, InputsRead);
rmesa->state.aos_count = nr;
+ radeon_bo_unmap(rmesa->radeon.dma.current);
+
return R300_FALLBACK_NONE;
}
if (rmesa->state.elt_dma_bo) {
radeon_bo_unref(rmesa->state.elt_dma_bo);
- rmesa->state.elt_dma_bo = 0;
+ rmesa->state.elt_dma_bo = NULL;
}
for (i = 0; i < rmesa->state.aos_count; i++) {
if (rmesa->state.aos[i].bo) {
- rmesa->state.aos[i].bo = radeon_bo_unref(rmesa->state.aos[i].bo);
+ radeon_bo_unref(rmesa->state.aos[i].bo);
+ rmesa->state.aos[i].bo = NULL;
}
}
+ radeonReleaseDmaRegion(&rmesa->radeon);
}
void r300EmitCacheFlush(r300ContextPtr rmesa)
R300_STATECHANGE(r300, fp);
R300_STATECHANGE(r300, r500fp);
- BEGIN_BATCH(14);
+ BEGIN_BATCH(7);
OUT_BATCH_REGSEQ(R500_US_CONFIG, 2);
OUT_BATCH(R500_ZERO_TIMES_ANYTHING_EQUALS_ZERO);
OUT_BATCH(0x0);
if (RADEON_DEBUG & DEBUG_IOCTL)
fprintf(stderr, "%s\n", __FUNCTION__);
- if (rmesa->swtcl.flush) {
- rmesa->swtcl.flush(rmesa);
- }
-
+ if (rmesa->radeon.dma.flush) {
+ rmesa->radeon.dma.flush(ctx);
+ }
+
if (rmesa->radeon.cmdbuf.cs->cdw) {
rcommonFlushCmdBuf(&rmesa->radeon, __FUNCTION__);
}
r300ContextPtr rmesa = R300_CONTEXT(ctx);
void *out;
- rmesa->state.elt_dma_bo = radeon_bo_open(rmesa->radeon.radeonScreen->bom,
- 0, n_elts * 4, 4,
- RADEON_GEM_DOMAIN_GTT, 0);
- rmesa->state.elt_dma_offset = 0;
+ radeonAllocDmaRegion(&rmesa->radeon, &rmesa->state.elt_dma_bo,
+ &rmesa->state.elt_dma_offset, n_elts * 4, 4);
radeon_bo_map(rmesa->state.elt_dma_bo, 1);
out = rmesa->state.elt_dma_bo->ptr + rmesa->state.elt_dma_offset;
memcpy(out, elts, n_elts * 4);
#include "r300_ioctl.h"
#include "r300_emit.h"
-static void flush_last_swtcl_prim( r300ContextPtr rmesa );
+static void flush_last_swtcl_prim( GLcontext *ctx);
void r300EmitVertexAOS(r300ContextPtr rmesa, GLuint vertex_size, struct radeon_bo *bo, GLuint offset);
/* Flush vertices in the current dma region.
*/
-static void flush_last_swtcl_prim( r300ContextPtr rmesa )
+static void flush_last_swtcl_prim( GLcontext *ctx )
{
+ r300ContextPtr rmesa = R300_CONTEXT(ctx);
+ struct radeon_dma *dma = &rmesa->radeon.dma;
+
+
if (RADEON_DEBUG & DEBUG_IOCTL)
fprintf(stderr, "%s\n", __FUNCTION__);
- rmesa->swtcl.flush = NULL;
- radeon_bo_unmap(rmesa->swtcl.bo);
- rcommonEnsureCmdBufSpace(rmesa,
- rmesa->hw.max_state_size + (12*sizeof(int)),
- __FUNCTION__);
- r300EmitState(rmesa);
- r300EmitVertexAOS(rmesa,
- rmesa->swtcl.vertex_size,
- rmesa->swtcl.bo,
- 0);
- r300EmitVbufPrim(rmesa,
- rmesa->swtcl.hw_primitive,
- rmesa->swtcl.numverts);
- r300EmitCacheFlush(rmesa);
- COMMIT_BATCH();
- rmesa->swtcl.numverts = 0;
+ dma->flush = NULL;
+
+ if (dma->current) {
+ GLuint current_offset = dma->current_used;
+
+ assert (dma->current_used +
+ rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 ==
+ dma->current_vertexptr);
+
+ radeon_bo_unmap(dma->current);
+ if (dma->current_used != dma->current_vertexptr) {
+ dma->current_used = dma->current_vertexptr;
+
+ rcommonEnsureCmdBufSpace(rmesa,
+ rmesa->hw.max_state_size + (12*sizeof(int)),
+ __FUNCTION__);
+ r300EmitState(rmesa);
+ r300EmitVertexAOS(rmesa,
+ rmesa->swtcl.vertex_size,
+ dma->current,
+ current_offset);
+
+ r300EmitVbufPrim(rmesa,
+ rmesa->swtcl.hw_primitive,
+ rmesa->swtcl.numverts);
+ r300EmitCacheFlush(rmesa);
+ COMMIT_BATCH();
+ }
+ radeonReleaseDmaRegion(&rmesa->radeon);
+ rmesa->swtcl.numverts = 0;
+ }
}
/* Alloc space in the current dma region.
r300AllocDmaLowVerts( r300ContextPtr rmesa, int nverts, int vsize )
{
GLuint bytes = vsize * nverts;
+ void *head;
- rmesa->swtcl.bo = radeon_bo_open(rmesa->radeon.radeonScreen->bom,
- 0, bytes, 4, RADEON_GEM_DOMAIN_GTT, 0);
- radeon_bo_map(rmesa->swtcl.bo, 1);
- if (rmesa->swtcl.flush == NULL) {
- rmesa->radeon.glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
- rmesa->swtcl.flush = flush_last_swtcl_prim;
+ if (!rmesa->radeon.dma.current || rmesa->radeon.dma.current_vertexptr + bytes > rmesa->radeon.dma.current->size) {
+ radeonRefillCurrentDmaRegion( &rmesa->radeon, bytes);
}
- return rmesa->swtcl.bo->ptr;
+
+ if (!rmesa->radeon.dma.flush) {
+ rmesa->radeon.glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
+ rmesa->radeon.dma.flush = flush_last_swtcl_prim;
+ }
+
+ ASSERT( vsize == rmesa->swtcl.vertex_size * 4 );
+ ASSERT( rmesa->radeon.dma.flush == flush_last_swtcl_prim );
+ ASSERT( rmesa->radeon.dma.current_used +
+ rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 ==
+ rmesa->dma.current_vertexptr );
+
+// fprintf(stderr,"current %p %x\n", rmesa->radeon.dma.current->ptr,
+// rmesa->radeon.dma.current_vertexptr);
+ head = (rmesa->radeon.dma.current->ptr + rmesa->radeon.dma.current_vertexptr);
+ rmesa->radeon.dma.current_vertexptr += bytes;
+ rmesa->swtcl.numverts += nverts;
+ return head;
}
static GLuint reduced_prim[] = {
r300UpdateShaderStates(rmesa);
r300EmitCacheFlush(rmesa);
- if (rmesa->swtcl.flush != NULL) {
- rmesa->swtcl.flush(rmesa);
- }
+ if (rmesa->radeon.dma.flush != NULL) {
+ rmesa->radeon.dma.flush(ctx);
+ }
}
static void r300RenderFinish(GLcontext *ctx)
};
struct radeon_dma {
- /* Active dma region. Allocations for vertices and retained
- * regions come from here. Also used for emitting random vertices,
- * these may be flushed by calling flush_current();
- */
- struct radeon_dma_region current;
-
- void (*flush)( GLcontext *ctx );
-
- char *buf0_address; /* start of buf[0], for index calcs */
- GLuint nr_released_bufs; /* flush after so many buffers released */
+ /* Active dma region. Allocations for vertices and retained
+ * regions come from here. Also used for emitting random vertices,
+ * these may be flushed by calling flush_current();
+ */
+ struct radeon_bo *current; /** Buffer that DMA memory is allocated from */
+ int current_used; /** Number of bytes allocated and forgotten about */
+ int current_vertexptr; /** End of active vertex region */
+
+ /**
+ * If current_vertexptr != current_used then flush must be non-zero.
+ * flush must be called before non-active vertex allocations can be
+ * performed.
+ */
+ void (*flush) (GLcontext *);
+
+ /* Number of "in-flight" DMA buffers, i.e. the number of buffers
+ * for which a DISCARD command is currently queued in the command buffer
+.
+ */
+ GLuint nr_released_bufs;
};
struct radeon_ioctl {
#define MAX_CMD_BUF_SZ (16*1024)
+#define MAX_DMA_BUF_SZ (64*1024)
+
struct radeon_store {
GLuint statenr;
GLuint primnr;
int texture_depth;
float initialMaxAnisotropy;
+ struct radeon_dma dma;
/* Rasterization and vertex state:
*/
GLuint TclFallback;
uint32_t *out;
uint32_t bo_size;
- memset(aos, 0, sizeof(struct radeon_aos));
if (stride == 0) {
- bo_size = size * 4;
+ radeonAllocDmaRegion(rmesa, &aos->bo, &aos->offset, size * 4, 32);
count = 1;
aos->stride = 0;
} else {
- bo_size = size * count * 4;
+ radeonAllocDmaRegion(rmesa, &aos->bo, &aos->offset, size * count * 4, 32);
aos->stride = size;
}
- aos->bo = radeon_bo_open(rmesa->radeonScreen->bom,
- 0, bo_size, 32, RADEON_GEM_DOMAIN_GTT, 0);
- aos->offset = 0;
+
aos->components = size;
aos->count = count;
- radeon_bo_map(aos->bo, 1);
+// radeon_bo_map(aos->bo, 1);
out = (uint32_t*)((char*)aos->bo->ptr + aos->offset);
switch (size) {
case 1: radeonEmitVec4(out, data, stride, count); break;
assert(0);
break;
}
- radeon_bo_unmap(aos->bo);
+// radeon_bo_unmap(aos->bo);
}
unmap_buffer(ctx->DrawBuffer->_StencilBuffer->Wrapped);
}
+void radeonRefillCurrentDmaRegion(radeonContextPtr rmesa, int size)
+{
+ size = MAX2(size, MAX_DMA_BUF_SZ * 16);
+
+ if (RADEON_DEBUG & (DEBUG_IOCTL | DEBUG_DMA))
+ fprintf(stderr, "%s\n", __FUNCTION__);
+
+ if (rmesa->dma.flush) {
+ radeon_bo_unmap(rmesa->dma.current);
+ rmesa->dma.flush(rmesa->glCtx);
+ }
+
+
+
+ if (rmesa->dma.nr_released_bufs > 4) {
+ rcommonFlushCmdBuf(rmesa, __FUNCTION__);
+ rmesa->dma.nr_released_bufs = 0;
+ }
+
+ if (rmesa->dma.current) {
+ radeon_bo_unref(rmesa->dma.current);
+ rmesa->dma.current = 0;
+ }
+
+ rmesa->dma.current = radeon_bo_open(rmesa->radeonScreen->bom,
+ 0, size, 4, RADEON_GEM_DOMAIN_GTT,
+ 0);
+
+ rmesa->dma.current_used = 0;
+ rmesa->dma.current_vertexptr = 0;
+ radeon_bo_map(rmesa->dma.current, 1);
+}
+
+/* Allocates a region from rmesa->dma.current. If there isn't enough
+ * space in current, grab a new buffer (and discard what was left of current)
+ */
+void radeonAllocDmaRegion(radeonContextPtr rmesa,
+ struct radeon_bo **pbo, int *poffset,
+ int bytes, int alignment)
+{
+ if (RADEON_DEBUG & DEBUG_IOCTL)
+ fprintf(stderr, "%s %d\n", __FUNCTION__, bytes);
+
+ if (rmesa->dma.flush)
+ rmesa->dma.flush(rmesa->glCtx);
+
+ assert(rmesa->dma.current_used == rmesa->dma.current_vertexptr);
+
+ alignment--;
+ rmesa->dma.current_used = (rmesa->dma.current_used + alignment) & ~alignment;
+
+ if (!rmesa->dma.current || rmesa->dma.current_used + bytes > rmesa->dma.current->size)
+ radeonRefillCurrentDmaRegion(rmesa, (bytes + 15) & ~15);
+
+ *poffset = rmesa->dma.current_used;
+ *pbo = rmesa->dma.current;
+ radeon_bo_ref(*pbo);
+
+ /* Always align to at least 16 bytes */
+ rmesa->dma.current_used = (rmesa->dma.current_used + bytes + 15) & ~15;
+ rmesa->dma.current_vertexptr = rmesa->dma.current_used;
+
+ assert(rmesa->dma.current_used <= rmesa->dma.current->size);
+}
+
+void radeonReleaseDmaRegion(radeonContextPtr rmesa)
+{
+ rmesa->dma.nr_released_bufs++;
+ radeon_bo_unref(rmesa->dma.current);
+ rmesa->dma.current = NULL;
+}
+
GLint x, GLint y);
GLubyte *radeon_ptr32(const struct radeon_renderbuffer * rrb,
GLint x, GLint y);
+void radeonRefillCurrentDmaRegion(radeonContextPtr rmesa, int size);
+void radeonAllocDmaRegion(radeonContextPtr rmesa,
+ struct radeon_bo **pbo, int *poffset,
+ int bytes, int alignment);
#endif
uint32_t fb_location;
uint32_t texture_offset;
unsigned dma_alloc_size;
+ uint32_t dma_buf_count;
unsigned cpendings;
driTextureObject texture_swapped;
driTexHeap *texture_heap;
return 0;
}
-static void legacy_track_pending(struct bo_manager_legacy *boml)
+static void legacy_track_pending(struct bo_manager_legacy *boml, int debug)
{
struct bo_legacy *bo_legacy;
struct bo_legacy *next;
legacy_get_current_age(boml);
bo_legacy = boml->pending_bos.pnext;
while (bo_legacy) {
+ if (debug)
+ fprintf(stderr,"pending %p %d %d %d\n", bo_legacy, bo_legacy->base.size,
+ boml->current_age, bo_legacy->pending);
next = bo_legacy->pnext;
if (legacy_is_pending(&(bo_legacy->base))) {
}
}
}
+static int legacy_wait_any_pending(struct bo_manager_legacy *boml)
+{
+ struct bo_legacy *bo_legacy;
+ struct bo_legacy *next;
+
+ legacy_get_current_age(boml);
+ bo_legacy = boml->pending_bos.pnext;
+ if (!bo_legacy)
+ return -1;
+ legacy_wait_pending(&bo_legacy->base);
+ return 0;
+}
+
static struct bo_legacy *bo_allocate(struct bo_manager_legacy *boml,
uint32_t size,
uint32_t alignment,
if (r) {
/* ptr is set to NULL if dma allocation failed */
bo_legacy->ptr = NULL;
- exit(0);
return r;
}
bo_legacy->ptr = boml->screen->gartTextures.map + base_offset;
bo_legacy->offset = boml->screen->gart_texture_offset + base_offset;
bo->size = size;
boml->dma_alloc_size += size;
+ boml->dma_buf_count++;
return 0;
}
return r;
}
boml->dma_alloc_size -= bo_legacy->base.size;
+ boml->dma_buf_count--;
return 0;
}
return NULL;
}
if (bo_legacy->base.domains & RADEON_GEM_DOMAIN_GTT) {
- legacy_track_pending(boml);
+ retry:
+ legacy_track_pending(boml, 0);
/* dma buffers */
+
r = bo_dma_alloc(&(bo_legacy->base));
if (r) {
- fprintf(stderr, "Ran out of GART memory (for %d)!\n", size);
+ if (legacy_wait_any_pending(boml) == -1) {
+ fprintf(stderr, "Ran out of GART memory (for %d)!\n", size);
fprintf(stderr, "Please consider adjusting GARTSize option.\n");
bo_free(bo_legacy);
exit(-1);
- return NULL;
+ }
+ goto retry;
+ return NULL;
}
} else {
bo_legacy->ptr = malloc(bo_legacy->base.size);
volatile int *buf = (int*)boml->screen->driScreen->pFB;
p = *buf;
}
-
return 0;
}
screen->sarea_priv_offset);
- rmesa->dma.buf0_address = rmesa->radeon.radeonScreen->buffers->list[0].address;
+ //rmesa->dma.buf0_address = rmesa->radeon.radeonScreen->buffers->list[0].address;
(void) memset( rmesa->radeon.texture_heaps, 0, sizeof( rmesa->radeon.texture_heaps ) );
make_empty_list( & rmesa->radeon.swapped );
radeonDestroySwtcl( rmesa->radeon.glCtx );
radeonReleaseArrays( rmesa->radeon.glCtx, ~0 );
- if (rmesa->dma.current.buf) {
- radeonReleaseDmaRegion( rmesa, &rmesa->dma.current, __FUNCTION__ );
+ if (rmesa->radeon.dma.current) {
+ radeonReleaseDmaRegion( rmesa, &rmesa->radeon.dma.current, __FUNCTION__ );
radeonFlushCmdBuf( rmesa, __FUNCTION__ );
}
/* Vertex buffers
*/
struct radeon_ioctl ioctl;
- struct radeon_dma dma;
struct radeon_store store;
/* A full state emit as of the first state emit in the main store, in case
* the context is lost.
rmesa->radeon.lost_context = GL_FALSE;
- nr_released_bufs = rmesa->dma.nr_released_bufs;
+ nr_released_bufs = rmesa->radeon.dma.nr_released_bufs;
saved_store = rmesa->store;
- rmesa->dma.nr_released_bufs = 0;
+ rmesa->radeon.dma.nr_released_bufs = 0;
rmesa->store = rmesa->backup_store;
radeonFlushCmdBufLocked( rmesa, __FUNCTION__ );
- rmesa->dma.nr_released_bufs = nr_released_bufs;
+ rmesa->radeon.dma.nr_released_bufs = nr_released_bufs;
rmesa->store = saved_store;
}
if (RADEON_DEBUG & DEBUG_IOCTL)
fprintf(stderr, "%s\n", __FUNCTION__);
- assert( rmesa->dma.flush == radeonFlushElts );
- rmesa->dma.flush = NULL;
+ assert( rmesa->radeon.dma.flush == radeonFlushElts );
+ rmesa->radeon.dma.flush = NULL;
/* Cope with odd number of elts:
*/
__FUNCTION__,
cmd[1].i, vertex_format, primitive);
- assert(!rmesa->dma.flush);
+ assert(!rmesa->radeon.dma.flush);
rmesa->radeon.glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
- rmesa->dma.flush = radeonFlushElts;
+ rmesa->radeon.dma.flush = radeonFlushElts;
rmesa->store.elts_start = ((char *)cmd) - rmesa->store.cmd_buf;
extern void radeonEmitWait( r100ContextPtr rmesa, GLuint flags );
extern void radeonFlushCmdBuf( r100ContextPtr rmesa, const char * );
-extern void radeonRefillCurrentDmaRegion( r100ContextPtr rmesa );
-
-extern void radeonAllocDmaRegion( r100ContextPtr rmesa,
- struct radeon_dma_region *region,
- int bytes,
- int alignment );
-
-extern void radeonReleaseDmaRegion( r100ContextPtr rmesa,
- struct radeon_dma_region *region,
- const char *caller );
extern void radeonFlush( GLcontext *ctx );
extern void radeonFinish( GLcontext *ctx );
*/
#define RADEON_NEWPRIM( rmesa ) \
do { \
- if ( rmesa->dma.flush ) \
- rmesa->dma.flush( rmesa->radeon.glCtx ); \
+ if ( rmesa->radeon.dma.flush ) \
+ rmesa->radeon.dma.flush( rmesa->radeon.glCtx ); \
} while (0)
/* Can accomodate several state changes and primitive changes without
*/
#define RADEON_FIREVERTICES( rmesa ) \
do { \
- if ( rmesa->store.cmd_used || rmesa->dma.flush ) { \
+ if ( rmesa->store.cmd_used || rmesa->radeon.dma.flush ) { \
radeonFlush( rmesa->radeon.glCtx ); \
} \
} while (0)