📄 r200_texmem.c
字号:
} }}/** * 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, r200TexObjPtr 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 ); do { ret = drmCommandWriteRead( rmesa->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 ); 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, r200TexObjPtr 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->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->glCtx ); } LOCK_HARDWARE( rmesa ); if ( t->base.memBlock == NULL ) { int heap; heap = driAllocateTexture( rmesa->texture_heaps, rmesa->nr_heaps, (driTextureObject *) t ); if ( heap == -1 ) { UNLOCK_HARDWARE( rmesa ); return -1; } /* Set the base offset of the texture image */ t->bufAddr = rmesa->r200Screen->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 = TEX_ALL; } /* Let the world know we've used this memory recently. */ driUpdateTextureLRU( (driTextureObject *) t ); UNLOCK_HARDWARE( rmesa ); /* 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->glCtx ); } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -