📄 r300_texmem.c
字号:
*/static void r300UploadSubImage(r300ContextPtr rmesa, r300TexObjPtr 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 (RADEON_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 (RADEON_DEBUG & DEBUG_TEXTURE) fprintf(stderr, "%s: texImage %d is NULL!\n", __FUNCTION__, level); return; } 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__); r300UploadRectSubImage(rmesa, t, texImage, x, y, width, height); return; } else if (texImage->IsClientData) { if (RADEON_DEBUG & DEBUG_TEXTURE) fprintf(stderr, "%s: image data is in GART client storage\n", __FUNCTION__); r300UploadGARTClientSubImage(rmesa, t, texImage, hwlevel, x, y, width, height); return; } else if (RADEON_DEBUG & DEBUG_TEXTURE) fprintf(stderr, "%s: image data is in normal memory\n", __FUNCTION__); imageWidth = texImage->Width; imageHeight = texImage->Height; offset = t->bufAddr; if (RADEON_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 > 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; } 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); } } 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); _mesa_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 r300UploadTexImages(r300ContextPtr rmesa, r300TexObjPtr t, GLuint face){ const int numLevels = t->base.lastLevel - t->base.firstLevel + 1; if (t->image_override) return 0; if (RADEON_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->base.totalSize == 0) return 0; if (RADEON_DEBUG & DEBUG_SYNC) { fprintf(stderr, "%s: Syncing\n", __FUNCTION__); radeonFinish(rmesa->radeon.glCtx); } LOCK_HARDWARE(&rmesa->radeon); if (t->base.memBlock == NULL) { int heap; heap = driAllocateTexture(rmesa->texture_heaps, rmesa->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->offset = t->bufAddr; if (!(t->base.tObj->Image[0][0]->IsClientData)) { /* hope it's safe to add that here... */ t->offset |= t->tile_bits; } } /* 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) { r300UploadSubImage(rmesa, t, i, 0, 0, t->image[face][i].width, t->image[face][i].height, face); } } t->base.dirty_images[face] = 0; } if (RADEON_DEBUG & DEBUG_SYNC) { fprintf(stderr, "%s: Syncing\n", __FUNCTION__); radeonFinish(rmesa->radeon.glCtx); } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -