From: Marek Olšák Date: Fri, 22 Jul 2011 16:58:30 +0000 (+0200) Subject: winsys/radeon: simplify how value queries work X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=28a336dc38c478b809544e7404c4d1fddd873333;p=mesa.git winsys/radeon: simplify how value queries work This drops the get_value query and adds a function query_info, which returns all the values in one nice structure. --- diff --git a/src/gallium/drivers/r300/r300_chipset.c b/src/gallium/drivers/r300/r300_chipset.c index 571986c3011..80148b80afb 100644 --- a/src/gallium/drivers/r300/r300_chipset.c +++ b/src/gallium/drivers/r300/r300_chipset.c @@ -31,9 +31,9 @@ * Radeons. */ /* Parse a PCI ID and fill an r300_capabilities struct with information. */ -void r300_parse_chipset(struct r300_capabilities* caps) +void r300_parse_chipset(uint32_t pci_id, struct r300_capabilities* caps) { - switch (caps->pci_id) { + switch (pci_id) { #define CHIPSET(pci_id, name, chipfamily) \ case pci_id: \ caps->family = CHIP_FAMILY_##chipfamily; \ @@ -43,7 +43,7 @@ void r300_parse_chipset(struct r300_capabilities* caps) default: fprintf(stderr, "r300: Warning: Unknown chipset 0x%x\nAborting...", - caps->pci_id); + pci_id); abort(); } diff --git a/src/gallium/drivers/r300/r300_chipset.h b/src/gallium/drivers/r300/r300_chipset.h index 4df6b5b6292..f96cdaf2580 100644 --- a/src/gallium/drivers/r300/r300_chipset.h +++ b/src/gallium/drivers/r300/r300_chipset.h @@ -43,16 +43,10 @@ enum r300_zmask_compression { /* Structure containing all the possible information about a specific Radeon * in the R3xx, R4xx, and R5xx families. */ struct r300_capabilities { - /* PCI ID */ - uint32_t pci_id; /* Chipset family */ int family; /* The number of vertex floating-point units */ unsigned num_vert_fpus; - /* The number of fragment pipes */ - unsigned num_frag_pipes; - /* The number of z pipes */ - unsigned num_z_pipes; /* The number of texture units. */ unsigned num_tex_units; /* Whether or not TCL is physically present */ @@ -121,6 +115,6 @@ enum { CHIP_FAMILY_RV570 }; -void r300_parse_chipset(struct r300_capabilities* caps); +void r300_parse_chipset(uint32_t pci_id, struct r300_capabilities* caps); #endif /* R300_CHIPSET_H */ diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c index d94ac74f0e5..2b3329e9f86 100644 --- a/src/gallium/drivers/r300/r300_context.c +++ b/src/gallium/drivers/r300/r300_context.c @@ -173,7 +173,7 @@ static boolean r300_setup_atoms(struct r300_context* r300) boolean is_rv350 = r300->screen->caps.is_rv350; boolean is_r500 = r300->screen->caps.is_r500; boolean has_tcl = r300->screen->caps.has_tcl; - boolean drm_2_6_0 = r300->rws->get_value(r300->rws, RADEON_VID_DRM_2_6_0); + boolean drm_2_6_0 = r300->screen->info.drm_minor >= 6; /* Create the actual atom list. * @@ -380,7 +380,7 @@ static void r300_init_states(struct pipe_context *pipe) if (r300->screen->caps.is_r500 || (r300->screen->caps.is_rv350 && - r300->rws->get_value(r300->rws, RADEON_VID_DRM_2_6_0))) { + r300->screen->info.drm_minor >= 6)) { OUT_CB_REG(R300_GB_Z_PEQ_CONFIG, 0); } END_CB; @@ -520,15 +520,15 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, "r300: DRM version: %d.%d.%d, Name: %s, ID: 0x%04x, GB: %d, Z: %d\n" "r300: GART size: %d MB, VRAM size: %d MB\n" "r300: AA compression RAM: %s, Z compression RAM: %s, HiZ RAM: %s\n", - rws->get_value(rws, RADEON_VID_DRM_MAJOR), - rws->get_value(rws, RADEON_VID_DRM_MINOR), - rws->get_value(rws, RADEON_VID_DRM_PATCHLEVEL), + r300->screen->info.drm_major, + r300->screen->info.drm_minor, + r300->screen->info.drm_patchlevel, screen->get_name(screen), - rws->get_value(rws, RADEON_VID_PCI_ID), - rws->get_value(rws, RADEON_VID_R300_GB_PIPES), - rws->get_value(rws, RADEON_VID_R300_Z_PIPES), - rws->get_value(rws, RADEON_VID_GART_SIZE) >> 20, - rws->get_value(rws, RADEON_VID_VRAM_SIZE) >> 20, + r300->screen->info.pci_id, + r300->screen->info.r300_num_gb_pipes, + r300->screen->info.r300_num_z_pipes, + r300->screen->info.gart_size >> 20, + r300->screen->info.vram_size >> 20, "YES", /* XXX really? */ r300->screen->caps.zmask_ram ? "YES" : "NO", r300->screen->caps.hiz_ram ? "YES" : "NO"); diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index d214af4cd5b..502aed3a20c 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -574,11 +574,12 @@ static void r300_emit_query_end_frag_pipes(struct r300_context *r300, struct r300_query *query) { struct r300_capabilities* caps = &r300->screen->caps; + uint32_t gb_pipes = r300->screen->info.r300_num_gb_pipes; CS_LOCALS(r300); - assert(caps->num_frag_pipes); + assert(gb_pipes); - BEGIN_CS(6 * caps->num_frag_pipes + 2); + BEGIN_CS(6 * gb_pipes + 2); /* I'm not so sure I like this switch, but it's hard to be elegant * when there's so many special cases... * @@ -587,7 +588,7 @@ static void r300_emit_query_end_frag_pipes(struct r300_context *r300, * 4-byte offset for each pipe. RV380 and older are special; they have * only two pipes, and the second pipe's enable is on bit 3, not bit 1, * so there's a chipset cap for that. */ - switch (caps->num_frag_pipes) { + switch (gb_pipes) { case 4: /* pipe 3 only */ OUT_CS_REG(R300_SU_REG_DEST, 1 << 3); @@ -613,7 +614,7 @@ static void r300_emit_query_end_frag_pipes(struct r300_context *r300, break; default: fprintf(stderr, "r300: Implementation error: Chipset reports %d" - " pixel pipes!\n", caps->num_frag_pipes); + " pixel pipes!\n", gb_pipes); abort(); } @@ -663,7 +664,7 @@ void r300_emit_query_end(struct r300_context* r300) return; if (caps->family == CHIP_FAMILY_RV530) { - if (caps->num_z_pipes == 2) + if (r300->screen->info.r300_num_z_pipes == 2) rv530_emit_query_end_double_z(r300, query); else rv530_emit_query_end_single_z(r300, query); diff --git a/src/gallium/drivers/r300/r300_query.c b/src/gallium/drivers/r300/r300_query.c index 782f041e926..000114129bf 100644 --- a/src/gallium/drivers/r300/r300_query.c +++ b/src/gallium/drivers/r300/r300_query.c @@ -49,9 +49,9 @@ static struct pipe_query *r300_create_query(struct pipe_context *pipe, q->buffer_size = 4096; if (r300screen->caps.family == CHIP_FAMILY_RV530) - q->num_pipes = r300screen->caps.num_z_pipes; + q->num_pipes = r300screen->info.r300_num_z_pipes; else - q->num_pipes = r300screen->caps.num_frag_pipes; + q->num_pipes = r300screen->info.r300_num_gb_pipes; insert_at_tail(&r300->query_list, q); diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c index c8df45fb3e7..d9378308ad0 100644 --- a/src/gallium/drivers/r300/r300_screen.c +++ b/src/gallium/drivers/r300/r300_screen.c @@ -327,9 +327,8 @@ static boolean r300_is_format_supported(struct pipe_screen* screen, unsigned sample_count, unsigned usage) { - struct radeon_winsys *rws = r300_screen(screen)->rws; uint32_t retval = 0; - boolean drm_2_8_0 = rws->get_value(rws, RADEON_VID_DRM_2_8_0); + boolean drm_2_8_0 = r300_screen(screen)->info.drm_minor >= 8; boolean is_r500 = r300_screen(screen)->caps.is_r500; boolean is_r400 = r300_screen(screen)->caps.is_r400; boolean is_color2101010 = format == PIPE_FORMAT_R10G10B10A2_UNORM || @@ -497,19 +496,17 @@ struct pipe_screen* r300_screen_create(struct radeon_winsys *rws) return NULL; } - r300screen->caps.pci_id = rws->get_value(rws, RADEON_VID_PCI_ID); - r300screen->caps.num_frag_pipes = rws->get_value(rws, RADEON_VID_R300_GB_PIPES); - r300screen->caps.num_z_pipes = rws->get_value(rws, RADEON_VID_R300_Z_PIPES); + rws->query_info(rws, &r300screen->info); r300_init_debug(r300screen); - r300_parse_chipset(&r300screen->caps); + r300_parse_chipset(r300screen->info.pci_id, &r300screen->caps); if (SCREEN_DBG_ON(r300screen, DBG_NO_ZMASK)) r300screen->caps.zmask_ram = 0; if (SCREEN_DBG_ON(r300screen, DBG_NO_HIZ)) r300screen->caps.hiz_ram = 0; - if (!rws->get_value(rws, RADEON_VID_DRM_2_8_0)) + if (r300screen->info.drm_minor < 8) r300screen->caps.has_us_format = FALSE; pipe_mutex_init(r300screen->num_contexts_mutex); diff --git a/src/gallium/drivers/r300/r300_screen.h b/src/gallium/drivers/r300/r300_screen.h index e5c53bf3500..82b2068e7a0 100644 --- a/src/gallium/drivers/r300/r300_screen.h +++ b/src/gallium/drivers/r300/r300_screen.h @@ -24,23 +24,20 @@ #ifndef R300_SCREEN_H #define R300_SCREEN_H -#include "pipe/p_screen.h" - #include "r300_chipset.h" - +#include "../../winsys/radeon/drm/radeon_winsys.h" +#include "pipe/p_screen.h" #include "util/u_slab.h" - #include -struct radeon_winsys; - struct r300_screen { /* Parent class */ struct pipe_screen screen; struct radeon_winsys *rws; - /* Chipset capabilities */ + /* Chipset info and capabilities. */ + struct radeon_info info; struct r300_capabilities caps; /* Memory pools. */ diff --git a/src/gallium/drivers/r300/r300_texture_desc.c b/src/gallium/drivers/r300/r300_texture_desc.c index da5778be65e..fe4f8dd5679 100644 --- a/src/gallium/drivers/r300/r300_texture_desc.c +++ b/src/gallium/drivers/r300/r300_texture_desc.c @@ -360,9 +360,9 @@ static void r300_setup_hyperz_properties(struct r300_screen *screen, unsigned i, pipes; if (screen->caps.family == CHIP_FAMILY_RV530) { - pipes = screen->caps.num_z_pipes; + pipes = screen->info.r300_num_z_pipes; } else { - pipes = screen->caps.num_frag_pipes; + pipes = screen->info.r300_num_gb_pipes; } for (i = 0; i <= tex->b.b.b.last_level; i++) { diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_cs.c b/src/gallium/winsys/radeon/drm/radeon_drm_cs.c index 0139de1973a..f0f4a70be3f 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_cs.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_cs.c @@ -308,8 +308,8 @@ static boolean radeon_drm_cs_validate(struct radeon_winsys_cs *rcs) { struct radeon_drm_cs *cs = radeon_drm_cs(rcs); - return cs->csc->used_gart < cs->ws->gart_size * 0.8 && - cs->csc->used_vram < cs->ws->vram_size * 0.8; + return cs->csc->used_gart < cs->ws->info.gart_size * 0.8 && + cs->csc->used_vram < cs->ws->info.vram_size * 0.8; } static void radeon_drm_cs_write_reloc(struct radeon_winsys_cs *rcs, diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c index 0474b381ade..473f388d121 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c @@ -103,17 +103,31 @@ static boolean radeon_set_fd_access(struct radeon_drm_cs *applier, return FALSE; } +static boolean radeon_get_drm_value(int fd, unsigned request, + const char *name, uint32_t *out) +{ + struct drm_radeon_info info = {0}; + int retval; + + info.value = (unsigned long)out; + info.request = request; + + retval = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info)); + if (retval) { + fprintf(stderr, "%s: Failed to get %s, error number %d\n", + __func__, name, retval); + return FALSE; + } + return TRUE; +} + /* Helper function to do the ioctls needed for setup and init. */ -static void do_ioctls(struct radeon_drm_winsys *winsys) +static boolean do_winsys_init(struct radeon_drm_winsys *ws) { struct drm_radeon_gem_info gem_info = {0}; - struct drm_radeon_info info = {0}; - int target = 0; int retval; drmVersionPtr version; - info.value = (unsigned long)⌖ - /* We do things in a specific order here. * * DRM version first. We need to be sure we're running on a KMS chipset. @@ -123,71 +137,76 @@ static void do_ioctls(struct radeon_drm_winsys *winsys) * for all Radeons. If this fails, we probably got handed an FD for some * non-Radeon card. * + * The GEM info is actually bogus on the kernel side, as well as our side + * (see radeon_gem_info_ioctl in radeon_gem.c) but that's alright because + * we don't actually use the info for anything yet. + * * The GB and Z pipe requests should always succeed, but they might not * return sensical values for all chipsets, but that's alright because * the pipe drivers already know that. - * - * The GEM info is actually bogus on the kernel side, as well as our side - * (see radeon_gem_info_ioctl in radeon_gem.c) but that's alright because - * we don't actually use the info for anything yet. */ + */ - version = drmGetVersion(winsys->fd); + /* Get DRM version. */ + version = drmGetVersion(ws->fd); if (version->version_major != 2 || version->version_minor < 3) { fprintf(stderr, "%s: DRM version is %d.%d.%d but this driver is " - "only compatible with 2.3.x (kernel 2.6.34) and later.\n", + "only compatible with 2.3.x (kernel 2.6.34) or later.\n", __FUNCTION__, version->version_major, version->version_minor, version->version_patchlevel); drmFreeVersion(version); - exit(1); + return FALSE; } - winsys->drm_major = version->version_major; - winsys->drm_minor = version->version_minor; - winsys->drm_patchlevel = version->version_patchlevel; + ws->info.drm_major = version->version_major; + ws->info.drm_minor = version->version_minor; + ws->info.drm_patchlevel = version->version_patchlevel; + drmFreeVersion(version); - info.request = RADEON_INFO_DEVICE_ID; - retval = drmCommandWriteRead(winsys->fd, DRM_RADEON_INFO, &info, sizeof(info)); - if (retval) { - fprintf(stderr, "%s: Failed to get PCI ID, " - "error number %d\n", __FUNCTION__, retval); - exit(1); - } - winsys->pci_id = target; + /* Get PCI ID. */ + if (!radeon_get_drm_value(ws->fd, RADEON_INFO_DEVICE_ID, "PCI ID", + &ws->info.pci_id)) + return FALSE; - info.request = RADEON_INFO_NUM_GB_PIPES; - retval = drmCommandWriteRead(winsys->fd, DRM_RADEON_INFO, &info, sizeof(info)); - if (retval) { - fprintf(stderr, "%s: Failed to get GB pipe count, " - "error number %d\n", __FUNCTION__, retval); - exit(1); - } - winsys->gb_pipes = target; + /* Check PCI ID. */ + switch (ws->info.pci_id) { +#define CHIPSET(pci_id, name, family) case pci_id: +#include "pci_ids/r300_pci_ids.h" +#undef CHIPSET + break; - info.request = RADEON_INFO_NUM_Z_PIPES; - retval = drmCommandWriteRead(winsys->fd, DRM_RADEON_INFO, &info, sizeof(info)); - if (retval) { - fprintf(stderr, "%s: Failed to get Z pipe count, " - "error number %d\n", __FUNCTION__, retval); - exit(1); + default: + fprintf(stderr, "radeon: Invalid PCI ID.\n"); + return FALSE; } - winsys->z_pipes = target; - retval = drmCommandWriteRead(winsys->fd, DRM_RADEON_GEM_INFO, + /* Get GEM info. */ + retval = drmCommandWriteRead(ws->fd, DRM_RADEON_GEM_INFO, &gem_info, sizeof(gem_info)); if (retval) { fprintf(stderr, "%s: Failed to get MM info, error number %d\n", __FUNCTION__, retval); - exit(1); + return FALSE; } - winsys->gart_size = gem_info.gart_size; - winsys->vram_size = gem_info.vram_size; + ws->info.gart_size = gem_info.gart_size; + ws->info.vram_size = gem_info.vram_size; - drmFreeVersion(version); + ws->num_cpus = sysconf(_SC_NPROCESSORS_ONLN); + + /* Generation-specific queries. */ + if (!radeon_get_drm_value(ws->fd, RADEON_INFO_NUM_GB_PIPES, + "GB pipe count", + &ws->info.r300_num_gb_pipes)) + return FALSE; - winsys->num_cpus = sysconf(_SC_NPROCESSORS_ONLN); + if (!radeon_get_drm_value(ws->fd, RADEON_INFO_NUM_Z_PIPES, + "Z pipe count", + &ws->info.r300_num_z_pipes)) + return FALSE; + + return TRUE; } static void radeon_winsys_destroy(struct radeon_winsys *rws) @@ -202,34 +221,10 @@ static void radeon_winsys_destroy(struct radeon_winsys *rws) FREE(rws); } -static uint32_t radeon_get_value(struct radeon_winsys *rws, - enum radeon_value_id id) +static void radeon_query_info(struct radeon_winsys *rws, + struct radeon_info *info) { - struct radeon_drm_winsys *ws = (struct radeon_drm_winsys *)rws; - - switch(id) { - case RADEON_VID_PCI_ID: - return ws->pci_id; - case RADEON_VID_R300_GB_PIPES: - return ws->gb_pipes; - case RADEON_VID_R300_Z_PIPES: - return ws->z_pipes; - case RADEON_VID_GART_SIZE: - return ws->gart_size; - case RADEON_VID_VRAM_SIZE: - return ws->vram_size; - case RADEON_VID_DRM_MAJOR: - return ws->drm_major; - case RADEON_VID_DRM_MINOR: - return ws->drm_minor; - case RADEON_VID_DRM_PATCHLEVEL: - return ws->drm_patchlevel; - case RADEON_VID_DRM_2_6_0: - return ws->drm_major*100 + ws->drm_minor >= 206; - case RADEON_VID_DRM_2_8_0: - return ws->drm_major*100 + ws->drm_minor >= 208; - } - return 0; + *info = ((struct radeon_drm_winsys *)rws)->info; } static boolean radeon_cs_request_feature(struct radeon_winsys_cs *rcs, @@ -268,16 +263,9 @@ struct radeon_winsys *radeon_drm_winsys_create(int fd) } ws->fd = fd; - do_ioctls(ws); - switch (ws->pci_id) { -#define CHIPSET(pci_id, name, family) case pci_id: -#include "pci_ids/r300_pci_ids.h" -#undef CHIPSET - break; - default: - goto fail; - } + if (!do_winsys_init(ws)) + goto fail; /* Create managers. */ ws->kman = radeon_bomgr_create(ws); @@ -289,7 +277,7 @@ struct radeon_winsys *radeon_drm_winsys_create(int fd) /* Set functions. */ ws->base.destroy = radeon_winsys_destroy; - ws->base.get_value = radeon_get_value; + ws->base.query_info = radeon_query_info; ws->base.cs_request_feature = radeon_cs_request_feature; radeon_bomgr_init_functions(ws); diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h index d5186bc4d17..347e1f1d11a 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h +++ b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h @@ -31,7 +31,6 @@ #define RADEON_DRM_WINSYS_H #include "radeon_winsys.h" - #include "os/os_thread.h" struct radeon_drm_winsys { @@ -40,20 +39,13 @@ struct radeon_drm_winsys { int fd; /* DRM file descriptor */ int num_cs; /* The number of command streams created. */ + struct radeon_info info; + struct pb_manager *kman; struct pb_manager *cman; - uint32_t pci_id; /* PCI ID */ - uint32_t gb_pipes; /* GB pipe count */ - uint32_t z_pipes; /* Z pipe count (rv530 only) */ - uint32_t gart_size; /* GART size. */ - uint32_t vram_size; /* VRAM size. */ uint32_t num_cpus; /* Number of CPUs. */ - unsigned drm_major; - unsigned drm_minor; - unsigned drm_patchlevel; - struct radeon_drm_cs *hyperz_owner; pipe_mutex hyperz_owner_mutex; struct radeon_drm_cs *cmask_owner; diff --git a/src/gallium/winsys/radeon/drm/radeon_winsys.h b/src/gallium/winsys/radeon/drm/radeon_winsys.h index 3a64e4abc35..915a9c5bad1 100644 --- a/src/gallium/winsys/radeon/drm/radeon_winsys.h +++ b/src/gallium/winsys/radeon/drm/radeon_winsys.h @@ -26,6 +26,20 @@ /* The public winsys interface header for the radeon driver. */ +/* R300 features in DRM. + * + * 2.6.0: + * - Hyper-Z + * - GB_Z_PEQ_CONFIG on rv350->r4xx + * - R500 FG_ALPHA_VALUE + * + * 2.8.0: + * - R500 US_FORMAT regs + * - R500 ARGB2101010 colorbuffer + * - CMask and AA regs + * - R16F/RG16F + */ + #include "pipebuffer/pb_bufmgr.h" #include "pipe/p_defines.h" #include "pipe/p_state.h" @@ -55,38 +69,17 @@ struct radeon_winsys_cs { uint32_t *buf; /* The command buffer. */ }; -enum radeon_value_id { - RADEON_VID_PCI_ID, - RADEON_VID_R300_GB_PIPES, - RADEON_VID_R300_Z_PIPES, - RADEON_VID_GART_SIZE, - RADEON_VID_VRAM_SIZE, - RADEON_VID_DRM_MAJOR, - RADEON_VID_DRM_MINOR, - RADEON_VID_DRM_PATCHLEVEL, - - /* These should probably go away: */ - - /* R300 features: - * - Hyper-Z - * - GB_Z_PEQ_CONFIG on rv350->r4xx - * - R500 FG_ALPHA_VALUE - * - * R600 features: - * - TBD - */ - RADEON_VID_DRM_2_6_0, +struct radeon_info { + uint32_t pci_id; + uint32_t gart_size; + uint32_t vram_size; - /* R300 features: - * - R500 US_FORMAT regs - * - R500 ARGB2101010 colorbuffer - * - CMask and AA regs - * - R16F/RG16F - * - * R600 features: - * - TBD - */ - RADEON_VID_DRM_2_8_0, + uint32_t drm_major; /* version */ + uint32_t drm_minor; + uint32_t drm_patchlevel; + + uint32_t r300_num_gb_pipes; + uint32_t r300_num_z_pipes; }; enum radeon_feature_id { @@ -103,13 +96,13 @@ struct radeon_winsys { void (*destroy)(struct radeon_winsys *ws); /** - * Query a system value from a winsys. + * Query an info structure from winsys. * * \param ws The winsys this function is called from. - * \param vid One of the RADEON_VID_* enums. + * \param info Return structure */ - uint32_t (*get_value)(struct radeon_winsys *ws, - enum radeon_value_id vid); + void (*query_info)(struct radeon_winsys *ws, + struct radeon_info *info); /************************************************************************** * Buffer management. Buffer attributes are mostly fixed over its lifetime.