--- radeon_context.c_orig	Thu May 29 13:45:41 2003
+++ radeon_context.c	Thu May 29 13:47:33 2003
@@ -141,6 +141,7 @@
     "GL_IBM_texture_mirrored_repeat",
     "GL_MESA_ycbcr_texture",
     "GL_NV_blend_square",
+    "GL_NV_texture_rectangle",
     "GL_SGIS_generate_mipmap",
     "GL_SGIS_texture_border_clamp",
     "GL_SGIS_texture_edge_clamp",
--- radeon_ioctl.c_orig	Thu May 29 23:18:31 2003
+++ radeon_ioctl.c	Thu May 29 23:38:46 2003
@@ -389,6 +389,72 @@
 #endif
 }
 
+/* using already shifted color_fmt! */
+void radeonEmitBlit( radeonContextPtr rmesa, /* FIXME: which drmMinor is required? */
+		   GLuint color_fmt,
+		   GLuint src_pitch,
+		   GLuint src_offset,
+		   GLuint dst_pitch,
+		   GLuint dst_offset,
+		   GLint srcx, GLint srcy,
+		   GLint dstx, GLint dsty,
+		   GLuint w, GLuint h )
+{
+   drmRadeonCmdHeader *cmd;
+
+   if (RADEON_DEBUG & DEBUG_IOCTL)
+      fprintf(stderr, "%s src %x/%x %d,%d dst: %x/%x %d,%d sz: %dx%d\n",
+	      __FUNCTION__, 
+	      src_pitch, src_offset, srcx, srcy,
+	      dst_pitch, dst_offset, dstx, dsty,
+	      w, h);
+
+   assert( (src_pitch & 63) == 0 );
+   assert( (dst_pitch & 63) == 0 );
+   assert( (src_offset & 1023) == 0 );
+   assert( (dst_offset & 1023) == 0 );
+   assert( w < (1<<16) );
+   assert( h < (1<<16) );
+
+   cmd = (drmRadeonCmdHeader *)radeonAllocCmdBuf( rmesa, 8 * sizeof(int),
+						  __FUNCTION__ );
+
+
+   cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
+   cmd[1].i = RADEON_CP_PACKET3_CNTL_BITBLT_MULTI | (5 << 16);
+   cmd[2].i = (RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
+	       RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+	       RADEON_GMC_BRUSH_NONE |
+	       color_fmt |
+	       RADEON_GMC_SRC_DATATYPE_COLOR |
+	       RADEON_ROP3_S |
+	       RADEON_DP_SRC_SOURCE_MEMORY |
+	       RADEON_GMC_CLR_CMP_CNTL_DIS |
+	       RADEON_GMC_WR_MSK_DIS );
+
+   cmd[3].i = ((src_pitch/64)<<22) | (src_offset >> 10);
+   cmd[4].i = ((dst_pitch/64)<<22) | (dst_offset >> 10);
+   cmd[5].i = (srcx << 16) | srcy;
+   cmd[6].i = (dstx << 16) | dsty; /* dst */
+   cmd[7].i = (w << 16) | h;
+}
+
+
+void radeonEmitWait( radeonContextPtr rmesa, GLuint flags )
+{
+   if (rmesa->dri.drmMinor >= 6) {
+      drmRadeonCmdHeader *cmd;
+
+      assert( !(flags & ~(RADEON_WAIT_2D|RADEON_WAIT_3D)) );
+      
+      cmd = (drmRadeonCmdHeader *)radeonAllocCmdBuf( rmesa, 1 * sizeof(int),
+						   __FUNCTION__ );
+      cmd[0].i = 0;
+      cmd[0].wait.cmd_type = RADEON_CMD_WAIT;
+      cmd[0].wait.flags = flags;
+   }
+}
+
 
 static int radeonFlushCmdBufLocked( radeonContextPtr rmesa, 
 				    const char * caller )
--- radeon_ioctl.h_orig	Thu May 29 23:18:27 2003
+++ radeon_ioctl.h	Thu May 29 23:21:07 2003
@@ -65,7 +65,17 @@
 			   GLuint n,
 			   GLuint offset );
 
+extern void radeonEmitBlit( radeonContextPtr rmesa,
+			    GLuint color_fmt,
+			    GLuint src_pitch,
+			    GLuint src_offset,
+			    GLuint dst_pitch,
+			    GLuint dst_offset,
+			    GLint srcx, GLint srcy,
+			    GLint dstx, GLint dsty,
+			    GLuint w, GLuint h );
 
+extern void radeonEmitWait( radeonContextPtr rmesa, GLuint flags );
 
 extern void radeonFlushCmdBuf( radeonContextPtr rmesa, const char * );
 extern void radeonRefillCurrentDmaRegion( radeonContextPtr rmesa );
--- radeon_texmem.c_orig	Thu May 29 14:27:37 2003
+++ radeon_texmem.c	Thu May 29 21:09:58 2003
@@ -76,6 +76,94 @@
  * Texture image conversions
  */
 
+
+static void radeonUploadRectSubImage( radeonContextPtr 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 = RADEON_GMC_DST_8BPP_CI;
+      break;
+   case 2:
+      blit_format = RADEON_GMC_DST_16BPP;
+      break;
+   case 4:
+      blit_format = RADEON_GMC_DST_32BPP;
+      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;
+
+   {	/* FIXME: use AGP-texturing if possible */
+      /* Data not in agp 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(&region, 0, sizeof(region));
+	 radeonAllocDmaRegion( rmesa, &region, lines * dstPitch, 64 );
+
+	 /* 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, tex, lines * src_pitch );
+	 } 
+	 else {
+	    char *buf = region.address;
+	    int i;
+	    for (i = 0 ; i < lines ; i++) {
+	       memcpy( buf, tex, src_pitch );
+	       buf += dstPitch;
+	       tex += src_pitch;
+	    }
+	 }
+
+	 radeonEmitWait( rmesa, RADEON_WAIT_3D );
+
+	 /* Blit to framebuffer
+	  */
+	 radeonEmitBlit( rmesa, 
+		       blit_format, 
+		       dstPitch, GET_START( &region ),   
+		       dstPitch, t->bufAddr,
+		       0, 0, 
+		       0, done, 
+		       width, lines );
+	 
+	 radeonEmitWait( rmesa, RADEON_WAIT_2D );
+
+	 radeonReleaseDmaRegion( rmesa, &region, __FUNCTION__ );
+	 done += lines;
+      }
+   }
+}
+
+
 /**
  * Upload the texture image associated with texture \a t at the specified
  * level at the address relative to \a start.
@@ -135,6 +223,16 @@
    if ( !texImage->Data ) {
       if ( RADEON_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 ( RADEON_DEBUG & DEBUG_TEXTURE )
+	 fprintf( stderr, "%s: image data is rectangular\n", __FUNCTION__);
+      radeonUploadRectSubImage( rmesa, t, texImage, x, y, width, height );
       return;
    }
 
--- radeon_texstate.c_orig	Thu May 29 13:58:16 2003
+++ radeon_texstate.c	Thu May 29 14:26:12 2003
@@ -147,6 +147,11 @@
       log2Height = tObj->Image[firstLevel]->HeightLog2;
       log2Depth = 0;
       break;
+   case GL_TEXTURE_RECTANGLE_NV:
+      firstLevel = lastLevel = 0;
+      log2Width = log2Height = 1; /* ? */
+      log2Depth = 0;
+      break;
    default:
       return;
    }
@@ -177,6 +182,10 @@
       if (texImage->IsCompressed) {
          size = texImage->CompressedSize;
       }
+      else if (tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
+      	 size = ((texImage->Width * texImage->TexFormat->TexelBytes + 63)
+      	         & ~63) * texImage->Height;
+      }
       else {
          int w = texImage->Width * texImage->TexFormat->TexelBytes;
          if (w < 32)
@@ -1461,6 +1470,31 @@
    return GL_TRUE;
 }
 
+static GLboolean enable_tex_rect( GLcontext *ctx, int unit )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+   struct gl_texture_object *tObj = texUnit->_Current;
+   radeonTexObjPtr t = (radeonTexObjPtr) tObj->DriverData;
+
+   if (!(t->pp_txformat & RADEON_TXFORMAT_NON_POWER2)) {
+      t->pp_txformat |= RADEON_TXFORMAT_NON_POWER2;
+      t->base.dirty_images[0] = ~0;
+   }
+
+   ASSERT(tObj->Target == GL_TEXTURE_RECTANGLE_NV);
+
+   if ( t->base.dirty_images[0] ) {
+      RADEON_FIREVERTICES( rmesa );
+      radeonSetTexImages( rmesa, tObj );
+      radeonUploadTexImages( rmesa, (radeonTexObjPtr) tObj->DriverData, 0 );
+      if ( !t->base.memBlock /* && !rmesa->prefer_agp_client_texturing  FIXME */ ) 
+	return GL_FALSE;
+   }
+
+   return GL_TRUE;
+}
+
 
 static GLboolean update_tex_common( GLcontext *ctx, int unit )
 {
@@ -1542,7 +1576,11 @@
 {
    struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
 
-   if ( texUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT) ) {
+   if ( texUnit->_ReallyEnabled & (TEXTURE_RECT_BIT) ) {
+      return (enable_tex_rect( ctx, unit ) &&
+	      update_tex_common( ctx, unit ));
+   }
+   else if ( texUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT) ) {
       return (enable_tex_2d( ctx, unit ) &&
 	      update_tex_common( ctx, unit ));
    }
