From 30b4e2a8937b744071ef7182e2f2223563cac9c9 Mon Sep 17 00:00:00 2001 From: Peter Zubaj Date: Wed, 20 Jun 2007 20:38:17 +0200 Subject: [PATCH] Texture upload using 2D blitter on r300. --- src/mesa/drivers/dri/r300/r300_cmdbuf.c | 58 ++++++++ src/mesa/drivers/dri/r300/r300_cmdbuf.h | 12 ++ src/mesa/drivers/dri/r300/r300_context.h | 15 ++- src/mesa/drivers/dri/r300/r300_reg.h | 1 + src/mesa/drivers/dri/r300/r300_state.c | 6 +- src/mesa/drivers/dri/r300/r300_texmem.c | 212 +++++++++++------------------ src/mesa/drivers/dri/r300/r300_texstate.c | 162 +++++++++++++--------- 7 files changed, 267 insertions(+), 199 deletions(-) diff --git a/src/mesa/drivers/dri/r300/r300_cmdbuf.c b/src/mesa/drivers/dri/r300/r300_cmdbuf.c index 7055286..4982178 100644 --- a/src/mesa/drivers/dri/r300/r300_cmdbuf.c +++ b/src/mesa/drivers/dri/r300/r300_cmdbuf.c @@ -569,6 +569,64 @@ void r300EmitBlit(r300ContextPtr rmesa, cmd[7].u = (w << 16) | h; } +void r300EmitBlit2D(r300ContextPtr rmesa, + GLuint color_fmt, + GLuint src_dst_tile, + GLuint src_pitch, + GLuint src_offset, + GLuint dst_pitch, + GLuint dst_offset, + GLint scl, GLint scr, + GLint sct, GLint scb, + GLint dstx, GLint dsty, + GLuint w, GLuint h) +{ + drm_r300_cmd_header_t *cmd; + + if (RADEON_DEBUG & DEBUG_IOCTL) + fprintf(stderr, + "%s sc %x/%x %d,%d - %d,%d dst: %x/%x %d,%d sz: %dx%d\n", + __FUNCTION__, src_pitch, src_offset, scl, scr, sct, scb, + 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));*/ + GLuint blit_format; + + switch (color_fmt) { + 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: + blit_format = RADEON_GMC_DST_8BPP_CI; + break; + } + + cmd = (drm_r300_cmd_header_t *) r300AllocCmdBuf(rmesa, 11, __FUNCTION__); + + cmd[0].u = 0; + cmd[0].header.cmd_type = R300_CMD_BLIT; + cmd[1].u = blit_format; + cmd[2].u = src_dst_tile; + cmd[3].u = src_pitch; + cmd[4].u = src_offset; + cmd[5].u = dst_pitch; + cmd[6].u = dst_offset; + cmd[7].u = (scl << 16) | scr; + cmd[8].u = (sct << 16) | scb; + cmd[9].u = (dsty << 16) | dstx; + cmd[10].u = (h << 16) | w; +} void r300EmitWait(r300ContextPtr rmesa, GLuint flags) { drm_r300_cmd_header_t *cmd; diff --git a/src/mesa/drivers/dri/r300/r300_cmdbuf.h b/src/mesa/drivers/dri/r300/r300_cmdbuf.h index acb6e38..45299bb 100644 --- a/src/mesa/drivers/dri/r300/r300_cmdbuf.h +++ b/src/mesa/drivers/dri/r300/r300_cmdbuf.h @@ -107,6 +107,18 @@ extern void r300EmitBlit(r300ContextPtr rmesa, GLuint dst_offset, GLint srcx, GLint srcy, GLint dstx, GLint dsty, GLuint w, GLuint h); + +extern void r300EmitBlit2D(r300ContextPtr rmesa, + GLuint color_fmt, + GLuint src_dst_tile, + GLuint src_pitch, + GLuint src_offset, + GLuint dst_pitch, + GLuint dst_offset, + GLint scl, GLint scr, + GLint sct, GLint scb, + GLint dstx, GLint dsty, + GLuint w, GLuint h); extern void r300EmitWait(r300ContextPtr rmesa, GLuint flags); extern void r300EmitLOAD_VBPNTR(r300ContextPtr rmesa, int start); diff --git a/src/mesa/drivers/dri/r300/r300_context.h b/src/mesa/drivers/dri/r300/r300_context.h index 076bb49..ebbf022 100644 --- a/src/mesa/drivers/dri/r300/r300_context.h +++ b/src/mesa/drivers/dri/r300/r300_context.h @@ -167,6 +167,18 @@ struct r300_dma { }; /* Texture related */ +typedef struct drm_r300_tex_image_t { + unsigned int dst_offset; /* dst ofset for blitter - relative to texture start */ + unsigned int dst_pitch; /* dst pitch for blitter */ + unsigned int src_dst_tile; /* value of register 1704 and 1700 - tile bits */ + + unsigned int clip_x, clip_y; /* destination clip x, y */ + unsigned int clip_width, clip_height; /* destination clip width and height */ + + unsigned int x, y; + unsigned int width, height; + const void __user *data; +} drm_r300_tex_image_t; typedef struct r300_tex_obj r300TexObj, *r300TexObjPtr; @@ -185,7 +197,8 @@ struct r300_tex_obj { brought into the texunit. */ - drm_radeon_tex_image_t image[6][RADEON_MAX_TEXTURE_LEVELS]; + drm_r300_tex_image_t image[6][RADEON_MAX_TEXTURE_LEVELS]; + GLuint transfer_size; /* used to set blit format */ /* Six, for the cube faces */ GLboolean image_override; /* Image overridden by GLX_EXT_tfp */ diff --git a/src/mesa/drivers/dri/r300/r300_reg.h b/src/mesa/drivers/dri/r300/r300_reg.h index 3ce09c1..73b0854 100644 --- a/src/mesa/drivers/dri/r300/r300_reg.h +++ b/src/mesa/drivers/dri/r300/r300_reg.h @@ -925,6 +925,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_TXO_ENDIAN_HALFDW_SWAP (3 << 0) # define R300_TXO_MACRO_TILE (1 << 2) # define R300_TXO_MICRO_TILE (1 << 3) +# define R300_TXO_UNKNOWN_TILE (1 << 4) # define R300_TXO_OFFSET_MASK 0xffffffe0 # define R300_TXO_OFFSET_SHIFT 5 /* END: Guess from R200 */ diff --git a/src/mesa/drivers/dri/r300/r300_state.c b/src/mesa/drivers/dri/r300/r300_state.c index e6c3946..521895c 100644 --- a/src/mesa/drivers/dri/r300/r300_state.c +++ b/src/mesa/drivers/dri/r300/r300_state.c @@ -1262,7 +1262,7 @@ static void r300SetupTextures(GLcontext * ctx) t->pitch_reg; r300->hw.tex.offset.cmd[R300_TEX_VALUE_0 + hw_tmu] = t->offset; - + if (t->offset & R300_TXO_MACRO_TILE) { WARN_ONCE("macro tiling enabled!\n"); } @@ -1270,6 +1270,10 @@ static void r300SetupTextures(GLcontext * ctx) if (t->offset & R300_TXO_MICRO_TILE) { WARN_ONCE("micro tiling enabled!\n"); } + + if (t->offset & R300_TXO_UNKNOWN_TILE) { + WARN_ONCE("unknown tiling enabled!\n"); + } r300->hw.tex.chroma_key.cmd[R300_TEX_VALUE_0 + hw_tmu] = 0x0; diff --git a/src/mesa/drivers/dri/r300/r300_texmem.c b/src/mesa/drivers/dri/r300/r300_texmem.c index 38f0da8..4e224d3 100644 --- a/src/mesa/drivers/dri/r300/r300_texmem.c +++ b/src/mesa/drivers/dri/r300/r300_texmem.c @@ -89,7 +89,7 @@ static void r300UploadGARTClientSubImage(r300ContextPtr rmesa, GLint width, GLint height) { const struct gl_texture_format *texFormat = texImage->TexFormat; - GLuint srcPitch, dstPitch; +/* GLuint srcPitch, dstPitch; */ int blit_format; int srcOffset; @@ -98,28 +98,28 @@ static void r300UploadGARTClientSubImage(r300ContextPtr rmesa, * 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) { + switch (t->transfer_size) { case 1: blit_format = R300_CP_COLOR_FORMAT_CI8; - srcPitch = t->image[0][0].width * texFormat->TexelBytes; - dstPitch = t->image[0][0].width * texFormat->TexelBytes; +/* srcPitch = t->image[0][0].width * texFormat->TexelBytes; + dstPitch = t->image[0][0].width * texFormat->TexelBytes;*/ break; case 2: blit_format = R300_CP_COLOR_FORMAT_RGB565; - srcPitch = t->image[0][0].width * texFormat->TexelBytes; - dstPitch = t->image[0][0].width * texFormat->TexelBytes; +/* srcPitch = t->image[0][0].width * texFormat->TexelBytes; + dstPitch = t->image[0][0].width * texFormat->TexelBytes;*/ break; case 4: blit_format = R300_CP_COLOR_FORMAT_ARGB8888; - srcPitch = t->image[0][0].width * texFormat->TexelBytes; - dstPitch = t->image[0][0].width * texFormat->TexelBytes; +/* srcPitch = t->image[0][0].width * texFormat->TexelBytes; + dstPitch = t->image[0][0].width * texFormat->TexelBytes;*/ break; - case 8: +/* case 8: case 16: blit_format = R300_CP_COLOR_FORMAT_CI8; srcPitch = t->image[0][0].width * texFormat->TexelBytes; dstPitch = t->image[0][0].width * texFormat->TexelBytes; - break; + break;*/ default: return; } @@ -140,7 +140,7 @@ static void r300UploadGARTClientSubImage(r300ContextPtr rmesa, r300EmitWait(rmesa, R300_WAIT_3D); - r300EmitBlit(rmesa, blit_format, + /*r300EmitBlit(rmesa, blit_format, srcPitch, srcOffset, dstPitch, @@ -148,7 +148,7 @@ static void r300UploadGARTClientSubImage(r300ContextPtr rmesa, x, y, t->image[0][hwlevel].x + x, - t->image[0][hwlevel].y + y, width, height); + t->image[0][hwlevel].y + y, width, height);*/ r300EmitWait(rmesa, R300_WAIT_2D); } @@ -161,7 +161,7 @@ static void r300UploadRectSubImage(r300ContextPtr rmesa, const struct gl_texture_format *texFormat = texImage->TexFormat; int blit_format, dstPitch, done; - switch (texFormat->TexelBytes) { + switch (t->transfer_size) { case 1: blit_format = R300_CP_COLOR_FORMAT_CI8; break; @@ -171,10 +171,10 @@ static void r300UploadRectSubImage(r300ContextPtr rmesa, case 4: blit_format = R300_CP_COLOR_FORMAT_ARGB8888; break; - case 8: +/* case 8: case 16: blit_format = R300_CP_COLOR_FORMAT_CI8; - break; + break;*/ default: return; } @@ -215,11 +215,11 @@ static void r300UploadRectSubImage(r300ContextPtr rmesa, */ GLuint srcPitch; srcPitch = texImage->RowStride * texFormat->TexelBytes; - r300EmitBlit(rmesa, + /*r300EmitBlit(rmesa, blit_format, srcPitch, r300GartOffsetFromVirtual(rmesa, texImage->Data), - dstPitch, t->bufAddr, 0, 0, 0, 0, width, height); + dstPitch, t->bufAddr, 0, 0, 0, 0, width, height);*/ } else { /* Data not in GART memory, or bad pitch. */ @@ -262,11 +262,11 @@ static void r300UploadRectSubImage(r300ContextPtr rmesa, /* Blit to framebuffer */ - r300EmitBlit(rmesa, + /*r300EmitBlit(rmesa, blit_format, dstPitch, GET_START(®ion), dstPitch | (t->tile_bits >> 16), - t->bufAddr, 0, 0, 0, done, width, lines); + t->bufAddr, 0, 0, 0, done, width, lines);*/ r300EmitWait(rmesa, R300_WAIT_2D); #ifdef USER_BUFFERS @@ -293,14 +293,14 @@ static void r300UploadSubImage(r300ContextPtr rmesa, r300TexObjPtr t, GLint imageWidth, imageHeight; GLint ret; drm_radeon_texture_t tex; - drm_radeon_tex_image_t tmp; + drm_r300_tex_image_t tmp; const int level = hwlevel + t->base.firstLevel; - + if (RADEON_DEBUG & DEBUG_TEXTURE) { fprintf(stderr, - "%s( %p, %p ) level/width/height/face = %d/%d/%d/%u\n", + "%s( %p, %p ) level/x/y/width/height/face = %d/%d/%d/%d/%d/%u\n", __FUNCTION__, (void *)t, (void *)t->base.tObj, level, - width, height, face); + x, y, width, height, face); } ASSERT(face < 6); @@ -366,119 +366,67 @@ static void r300UploadSubImage(r300ContextPtr rmesa, r300TexObjPtr t, (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 > 4) { - const int log2TexelBytes = - (3 + (texImage->TexFormat->TexelBytes >> 4)); - tex.format = RADEON_TXFORMAT_I8; /* any 1-byte texel format */ - tex.pitch = - MAX2((texImage->Width * texImage->TexFormat->TexelBytes) / - 64, 1); - tex.height = imageHeight; - tex.width = imageWidth << log2TexelBytes; - tex.offset += (tmp.x << log2TexelBytes) & ~1023; - tmp.x = tmp.x % (1024 >> log2TexelBytes); - tmp.width = tmp.width << log2TexelBytes; - } else if (texImage->TexFormat->TexelBytes) { - /* use multi-byte upload scheme */ - tex.height = imageHeight; - tex.width = imageWidth; - switch (texImage->TexFormat->TexelBytes) { - case 1: - tex.format = RADEON_TXFORMAT_I8; - break; - case 2: - tex.format = RADEON_TXFORMAT_AI88; - break; - case 4: - tex.format = RADEON_TXFORMAT_ARGB8888; - break; - } - tex.pitch = - MAX2((texImage->Width * texImage->TexFormat->TexelBytes) / - 64, 1); - tex.offset += tmp.x & ~1023; - tmp.x = tmp.x % 1024; - - if (t->tile_bits & R300_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 1 - if ((t->tile_bits & R300_TXO_MACRO_TILE) && - (texImage->Width * texImage->TexFormat->TexelBytes >= 256) - && ((!(t->tile_bits & R300_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; - } -#endif - } 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 = RADEON_TXFORMAT_I8; /* any 1-byte texel format */ - tex.pitch = (R300_BLIT_WIDTH_BYTES / 64); - tex.height = (imageHeight + 3) / 4; - tex.width = (imageWidth + 3) / 4; - if ((t->format & R300_TX_FORMAT_DXT1) == R300_TX_FORMAT_DXT1) { - tex.width *= 8; + int done; + + + int k = 0; + for (done = 0; done < height;) { + + int lines = + MIN2(t->image[face][hwlevel].height - done, RADEON_BUFFER_SIZE / t->image[face][hwlevel].dst_pitch); + int src_pitch; + int dst_pitch; + char *tex; + + dst_pitch = t->image[face][hwlevel].dst_pitch; + src_pitch = t->image[face][hwlevel].width * t->transfer_size; + + tex = (char *)texImage->Data + done * src_pitch; + + struct r300_dma_region region; + + memset(®ion, 0, sizeof(region)); + r300AllocDmaRegion(rmesa, ®ion, lines * dst_pitch, + 1024); + + /* Copy texdata to dma: + */ + if (src_pitch == dst_pitch) { + memcpy(region.address + region.start, tex, + lines * dst_pitch); } else { - tex.width *= 16; - } - } - - LOCK_HARDWARE(&rmesa->radeon); - do { - ret = - drmCommandWriteRead(rmesa->radeon.dri.fd, - DRM_RADEON_TEXTURE, &tex, - sizeof(drm_radeon_texture_t)); - if (ret) { - if (RADEON_DEBUG & DEBUG_IOCTL) - fprintf(stderr, - "DRM_RADEON_TEXTURE: again!\n"); - usleep(1); + char *buf = region.address + region.start; + int i; + for (i = 0; i < lines; i++) { + memcpy(buf, tex, src_pitch); + buf += dst_pitch; + tex += src_pitch; + } } - } while (ret == -EAGAIN); - UNLOCK_HARDWARE(&rmesa->radeon); + r300EmitWait(rmesa, R300_WAIT_3D); - 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); - _mesa_exit(-1); + /* Blit to framebuffer + */ + r300EmitBlit2D(rmesa, + t->transfer_size, + t->image[face][hwlevel].src_dst_tile, + dst_pitch, + GET_START(®ion), + dst_pitch, + t->bufAddr + t->image[face][hwlevel].dst_offset, + t->image[face][hwlevel].clip_x, t->image[face][hwlevel].clip_x + t->image[face][hwlevel].clip_width, + t->image[face][hwlevel].clip_y, t->image[face][hwlevel].clip_y + t->image[face][hwlevel].clip_height, + t->image[face][hwlevel].x, t->image[face][hwlevel].y + done, + t->image[face][hwlevel].width, lines); + + r300EmitWait(rmesa, R300_WAIT_2D); +#ifdef USER_BUFFERS + r300_mem_use(rmesa, region.buf->id); +#endif + r300ReleaseDmaRegion(rmesa, ®ion, __FUNCTION__); + + done += lines; } } diff --git a/src/mesa/drivers/dri/r300/r300_texstate.c b/src/mesa/drivers/dri/r300/r300_texstate.c index 1d2909f..8337b53 100644 --- a/src/mesa/drivers/dri/r300/r300_texstate.c +++ b/src/mesa/drivers/dri/r300/r300_texstate.c @@ -137,7 +137,8 @@ static void r300SetTexImages(r300ContextPtr rmesa, r300TexObjPtr t = (r300TexObjPtr) tObj->DriverData; const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel]; - GLint curOffset, blitWidth; + GLint curOffset; + GLint width_coef, height_coef; GLint i, texelBytes; GLint numLevels; GLint log2Width, log2Height, log2Depth; @@ -172,35 +173,21 @@ static void r300SetTexImages(r300ContextPtr rmesa, * memory organized as a rectangle of width BLIT_WIDTH_BYTES. */ curOffset = 0; - blitWidth = R300_BLIT_WIDTH_BYTES; t->tile_bits = 0; /* figure out if this texture is suitable for tiling. */ -#if 0 /* Disabled for now */ if (texelBytes) { - if ((tObj->Target != GL_TEXTURE_RECTANGLE_NV) && - /* texrect might be able to use micro tiling too in theory? */ - (baseImage->Height > 1)) { - - /* allow 32 (bytes) x 1 mip (which will use two times the space - the non-tiled version would use) max if base texture is large enough */ - if ((numLevels == 1) || - (((baseImage->Width * texelBytes / - baseImage->Height) <= 32) - && (baseImage->Width * texelBytes > 64)) - || - ((baseImage->Width * texelBytes / - baseImage->Height) <= 16)) { - t->tile_bits |= R300_TXO_MICRO_TILE; - } - } - - if (tObj->Target != GL_TEXTURE_RECTANGLE_NV) { - /* we can set macro tiling even for small textures, they will be untiled anyway */ - t->tile_bits |= R300_TXO_MACRO_TILE; - } + if (tObj->Target != GL_TEXTURE_RECTANGLE_NV) + /* use tiling for all pot textures */ + t->tile_bits |= R300_TXO_MACRO_TILE | R300_TXO_MICRO_TILE; + } else if (tObj->Image[0][t->base.firstLevel]->IsCompressed) { + /* use micro tiling only for DXT1 */ + if ((t->format & R300_TX_FORMAT_DXT1) == R300_TX_FORMAT_DXT1) + t->tile_bits |= R300_TXO_MICRO_TILE; + + /* we can set macro tiling even for small textures, they will be untiled anyway */ + t->tile_bits |= R300_TXO_MACRO_TILE; } -#endif for (i = 0; i < numLevels; i++) { const struct gl_texture_image *texImage; @@ -212,30 +199,11 @@ static void r300SetTexImages(r300ContextPtr rmesa, /* find image size in bytes */ if (texImage->IsCompressed) { - if ((t->format & R300_TX_FORMAT_DXT1) == - R300_TX_FORMAT_DXT1) { - // fprintf(stderr,"DXT 1 %d %08X\n", texImage->Width, t->format); - if ((texImage->Width + 3) < 8) /* width one block */ - size = texImage->CompressedSize * 4; - else if ((texImage->Width + 3) < 16) - size = texImage->CompressedSize * 2; - else - size = texImage->CompressedSize; - } else { - /* DXT3/5, 16 bytes per block */ - WARN_ONCE - ("DXT 3/5 suffers from multitexturing problems!\n"); - // fprintf(stderr,"DXT 3/5 %d\n", texImage->Width); - if ((texImage->Width + 3) < 8) - size = texImage->CompressedSize * 2; - else - size = texImage->CompressedSize; - } + size = texImage->CompressedSize; } else if (tObj->Target == GL_TEXTURE_RECTANGLE_NV) { size = ((texImage->Width * texelBytes + 63) & ~63) * texImage->Height; - blitWidth = 64 / texelBytes; } else if (t->tile_bits & R300_TXO_MICRO_TILE) { /* tile pattern is 16 bytes x2. mipmaps stay 32 byte aligned, though the actual offset may be different (if texture is less than @@ -244,11 +212,9 @@ static void r300SetTexImages(r300ContextPtr rmesa, size = (w * ((texImage->Height + 1) / 2)) * texImage->Depth; - blitWidth = MAX2(texImage->Width, 64 / texelBytes); } else { int w = (texImage->Width * texelBytes + 31) & ~31; size = w * texImage->Height * texImage->Depth; - blitWidth = MAX2(texImage->Width, 64 / texelBytes); } assert(size > 0); @@ -264,23 +230,80 @@ static void r300SetTexImages(r300ContextPtr rmesa, */ curOffset = (curOffset + 0x1f) & ~0x1f; - - if (texelBytes) { - /* fix x and y coords up later together with offset */ - t->image[0][i].x = curOffset; - t->image[0][i].y = 0; - t->image[0][i].width = - MIN2(size / texelBytes, blitWidth); - t->image[0][i].height = - (size / texelBytes) / t->image[0][i].width; + + height_coef = 1; + if (texImage->IsCompressed) + height_coef = 4; + + width_coef = 1; + if (texImage->IsCompressed) { + t->transfer_size = 2; + /* DXT 3/5 have two times width */ + if ((t->format & R300_TX_FORMAT_DXT1) == R300_TX_FORMAT_DXT1) + width_coef = 1; + else + width_coef = 2; + } else if (texelBytes >= 4) { + /* textures with more then 4 bytes on texel */ + t->transfer_size = 4; + width_coef = texelBytes / 4; + } else if (texelBytes >= 2) + t->transfer_size = 2; + else + t->transfer_size = 1; + + t->image[0][i].clip_x = 0; + t->image[0][i].clip_y = 0; + + /* set tiling register for blit from base texture tiling */ + t->image[0][i].src_dst_tile = t->tile_bits >> 2; + + /* for small sizes turn off macro tiling */ + if (texImage->IsCompressed && (texImage->Width <= 32)) { + t->image[0][i].src_dst_tile &= ~(R300_TXO_MACRO_TILE >> 2); } else { - t->image[0][i].x = curOffset % R300_BLIT_WIDTH_BYTES; - t->image[0][i].y = curOffset / R300_BLIT_WIDTH_BYTES; - t->image[0][i].width = - MIN2(size, R300_BLIT_WIDTH_BYTES); - t->image[0][i].height = size / t->image[0][i].width; + if (t->transfer_size < 2 ) { + if (texImage->Width <= 32) + t->image[0][i].src_dst_tile &= ~(R300_TXO_MACRO_TILE >> 2); + } else if (texImage->Width <= 16) + t->image[0][i].src_dst_tile &= ~(R300_TXO_MACRO_TILE >> 2); + } + + /* correct start tiling on first level */ + if ((i == 0) && (t->image[0][i].src_dst_tile != (t->tile_bits >> 2))) + t->tile_bits = t->image[0][i].src_dst_tile << 2; + + t->image[0][i].x = 0; + t->image[0][i].y = 0; + + if (texImage->IsCompressed) { + if ((t->format & R300_TX_FORMAT_DXT1) != R300_TX_FORMAT_DXT1) + t->image[0][i].width = MAX2(width_coef * texImage->Width, 16); /* guess */ + else + t->image[0][i].width = MAX2(width_coef * texImage->Width, 4); + } else + t->image[0][i].width = width_coef * texImage->Width; + + t->image[0][i].height = texImage->Height / height_coef; + if (t->image[0][i].height <= 0) + t->image[0][i].height = 1; + + t->image[0][i].dst_offset = curOffset; + t->image[0][i].dst_pitch = MAX2(t->image[0][i].width * t->transfer_size, 16); + + if (texImage->IsCompressed) { + if ((t->format & R300_TX_FORMAT_DXT1) != R300_TX_FORMAT_DXT1) + t->image[0][i].clip_width = MAX2(width_coef * texImage->Width, 16); + else + t->image[0][i].clip_width = MAX2(width_coef * texImage->Width, 8); } + else + t->image[0][i].clip_width = width_coef * texImage->Width; + t->image[0][i].clip_height = texImage->Height / height_coef; + if (t->image[0][i].clip_height <= 0) + t->image[0][i].clip_height = 1; + if (RADEON_DEBUG & DEBUG_TEXTURE) fprintf(stderr, "level %d: %dx%d x=%d y=%d w=%d h=%d size=%d at %d\n", @@ -307,6 +330,14 @@ static void r300SetTexImages(r300ContextPtr rmesa, t->image[face][i].width = t->image[0][i].width; t->image[face][i].height = t->image[0][i].height; + + t->image[face][i].dst_offset = t->base.totalSize * face + t->image[0][i].dst_offset; + t->image[face][i].dst_pitch = t->image[0][i].dst_pitch; + t->image[face][i].src_dst_tile = t->image[0][i].src_dst_tile; + t->image[face][i].clip_x = t->image[0][i].clip_x; + t->image[face][i].clip_y = t->image[0][i].clip_y; + t->image[face][i].clip_width = t->image[0][i].clip_width; + t->image[face][i].clip_height = t->image[0][i].clip_height; } } t->base.totalSize *= 6; /* total texmem needed */ @@ -328,13 +359,14 @@ static void r300SetTexImages(r300ContextPtr rmesa, * requires 64-byte aligned pitches, and we may/may not need the * blitter. NPOT only! */ + /* I dont know what is minimal pitch for 2d blitter, and this is probably wrong */ if (baseImage->IsCompressed) { t->pitch = - (tObj->Image[0][t->base.firstLevel]->Width + 63) & ~(63); + (tObj->Image[0][t->base.firstLevel]->Width + 15) & ~(15); } else if (tObj->Target == GL_TEXTURE_RECTANGLE_NV) { - unsigned int align = blitWidth - 1; + unsigned int align = tObj->Image[0][t->base.firstLevel]->Width - 1; t->pitch = ((tObj->Image[0][t->base.firstLevel]->Width * - texelBytes) + 63) & ~(63); + texelBytes) + 15) & ~(15); t->size |= R300_TX_SIZE_TXPITCH_EN; if (!t->image_override) t->pitch_reg = @@ -343,7 +375,7 @@ static void r300SetTexImages(r300ContextPtr rmesa, } else { t->pitch = ((tObj->Image[0][t->base.firstLevel]->Width * - texelBytes) + 63) & ~(63); + texelBytes) + 15) & ~(15); } t->dirty_state = TEX_ALL; -- 1.5.2.1