struct pipe_screen* r300_screen_create(struct radeon_winsys *rws) { struct r300_screen *r300screen = CALLOC_STRUCT(r300_screen); if (!r300screen) { FREE(r300screen); return NULL; } rws->query_info(rws, &r300screen->info); r300_init_debug(r300screen); 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 (r300screen->info.drm_minor < 8) r300screen->caps.has_us_format = FALSE; r300screen->rws = rws; r300screen->screen.destroy = r300_destroy_screen; r300screen->screen.get_name = r300_get_name; r300screen->screen.get_vendor = r300_get_vendor; r300screen->screen.get_param = r300_get_param; r300screen->screen.get_shader_param = r300_get_shader_param; r300screen->screen.get_paramf = r300_get_paramf; r300screen->screen.get_video_param = r300_get_video_param; r300screen->screen.is_format_supported = r300_is_format_supported; r300screen->screen.is_video_format_supported = vl_video_buffer_is_format_supported; r300screen->screen.context_create = r300_create_context; r300screen->screen.fence_reference = r300_fence_reference; r300screen->screen.fence_signalled = r300_fence_signalled; r300screen->screen.fence_finish = r300_fence_finish; r300_init_screen_resource_functions(r300screen); util_format_s3tc_init(); return &r300screen->screen; }
boolean r300_texture_desc_init(struct r300_screen *rscreen, struct r300_texture_desc *desc, const struct pipe_resource *base, enum r300_buffer_tiling microtile, enum r300_buffer_tiling macrotile, unsigned stride_in_bytes_override, unsigned max_buffer_size) { desc->b.b = *base; desc->b.b.screen = &rscreen->screen; desc->stride_in_bytes_override = stride_in_bytes_override; if (microtile == R300_BUFFER_SELECT_LAYOUT || macrotile == R300_BUFFER_SELECT_LAYOUT) { r300_setup_tiling(rscreen, desc); } else { desc->microtile = microtile; desc->macrotile[0] = macrotile; assert(desc->b.b.last_level == 0); } r300_setup_flags(desc); r300_setup_cbzb_flags(rscreen, desc); /* Setup the miptree description. */ r300_setup_miptree(rscreen, desc, TRUE); /* If the required buffer size is larger the given max size, * try again without the alignment for the CBZB clear. */ if (max_buffer_size && desc->size_in_bytes > max_buffer_size) { r300_setup_miptree(rscreen, desc, FALSE); } r300_texture_3d_fix_mipmapping(rscreen, desc); if (max_buffer_size) { /* Make sure the buffer we got is large enough. */ if (desc->size_in_bytes > max_buffer_size) { fprintf(stderr, "r300: texture_from_handle: The buffer is not " "large enough. Got: %i, Need: %i, Info:\n", max_buffer_size, desc->size_in_bytes); r300_tex_print_info(rscreen, desc, "texture_from_handle"); return FALSE; } desc->buffer_size_in_bytes = max_buffer_size; } else { desc->buffer_size_in_bytes = desc->size_in_bytes; } if (SCREEN_DBG_ON(rscreen, DBG_TEX)) r300_tex_print_info(rscreen, desc, "texture_from_handle"); return TRUE; }
static void r300_setup_cmask_properties(struct r300_screen *screen, struct r300_resource *tex) { static unsigned cmask_align_x[4] = {16, 32, 48, 32}; static unsigned cmask_align_y[4] = {16, 16, 16, 32}; unsigned pipes, stride, cmask_num_dw, cmask_max_size; /* We need an AA colorbuffer, no mipmaps. */ if (tex->b.b.nr_samples <= 1 || tex->b.b.last_level > 0 || util_format_is_depth_or_stencil(tex->b.b.format)) { return; } /* FP16 AA needs R500 and a fairly new DRM. */ if ((tex->b.b.format == PIPE_FORMAT_R16G16B16A16_FLOAT || tex->b.b.format == PIPE_FORMAT_R16G16B16X16_FLOAT) && (!screen->caps.is_r500 || screen->info.drm_minor < 29)) { return; } if (SCREEN_DBG_ON(screen, DBG_NO_CMASK)) { return; } /* CMASK is part of raster pipes. The number of Z pipes doesn't matter. */ pipes = screen->info.r300_num_gb_pipes; /* The single-pipe cards have 5120 dwords of CMASK RAM, * the other cards have 4096 dwords of CMASK RAM per pipe. */ cmask_max_size = pipes == 1 ? 5120 : pipes * 4096; stride = r300_stride_to_width(tex->b.b.format, tex->tex.stride_in_bytes[0]); stride = align(stride, 16); /* Get the CMASK size in dwords. */ cmask_num_dw = r300_pixels_to_dwords(stride, tex->b.b.height0, cmask_align_x[pipes-1], cmask_align_y[pipes-1]); /* Check the CMASK size against the CMASK memory limit. */ if (cmask_num_dw <= cmask_max_size) { tex->tex.cmask_dwords = cmask_num_dw; tex->tex.cmask_stride_in_pixels = util_align_npot(stride, cmask_align_x[pipes-1]); } }
static void r300_setup_tiling(struct r300_screen *screen, struct r300_resource *tex) { enum pipe_format format = tex->b.b.b.format; boolean rv350_mode = screen->caps.family >= CHIP_FAMILY_R350; boolean is_zb = util_format_is_depth_or_stencil(format); boolean dbg_no_tiling = SCREEN_DBG_ON(screen, DBG_NO_TILING); tex->tex.microtile = RADEON_LAYOUT_LINEAR; tex->tex.macrotile[0] = RADEON_LAYOUT_LINEAR; if (!util_format_is_plain(format)) { return; } /* If height == 1, disable microtiling except for zbuffer. */ if (!is_zb && (tex->b.b.b.height0 == 1 || dbg_no_tiling)) { return; } /* Set microtiling. */ switch (util_format_get_blocksize(format)) { case 1: case 4: case 8: tex->tex.microtile = RADEON_LAYOUT_TILED; break; case 2: tex->tex.microtile = RADEON_LAYOUT_SQUARETILED; break; } if (dbg_no_tiling) { return; } /* Set macrotiling. */ if (r300_texture_macro_switch(tex, 0, rv350_mode, DIM_WIDTH) && r300_texture_macro_switch(tex, 0, rv350_mode, DIM_HEIGHT)) { tex->tex.macrotile[0] = RADEON_LAYOUT_TILED; } }
static void r300_setup_tiling(struct r300_screen *screen, struct r300_texture_desc *desc) { struct r300_winsys_screen *rws = screen->rws; enum pipe_format format = desc->b.b.format; boolean rv350_mode = screen->caps.family >= CHIP_FAMILY_R350; boolean is_zb = util_format_is_depth_or_stencil(format); boolean dbg_no_tiling = SCREEN_DBG_ON(screen, DBG_NO_TILING); if (!util_format_is_plain(format)) { return; } /* If height == 1, disable microtiling except for zbuffer. */ if (!is_zb && (desc->b.b.height0 == 1 || dbg_no_tiling)) { return; } /* Set microtiling. */ switch (util_format_get_blocksize(format)) { case 1: case 4: desc->microtile = R300_BUFFER_TILED; break; case 2: case 8: if (rws->get_value(rws, R300_VID_SQUARE_TILING_SUPPORT)) { desc->microtile = R300_BUFFER_SQUARETILED; } break; } if (dbg_no_tiling) { return; } /* Set macrotiling. */ if (r300_texture_macro_switch(desc, 0, rv350_mode, DIM_WIDTH) && r300_texture_macro_switch(desc, 0, rv350_mode, DIM_HEIGHT)) { desc->macrotile[0] = R300_BUFFER_TILED; } }
static void r300_setup_cbzb_flags(struct r300_screen *rscreen, struct r300_resource *tex) { unsigned i, bpp; boolean first_level_valid; bpp = util_format_get_blocksizebits(tex->b.b.b.format); /* 1) The texture must be point-sampled, * 2) The depth must be 16 or 32 bits. * 3) If the midpoint ZB offset is not aligned to 2048, it returns garbage * with certain texture sizes. Macrotiling ensures the alignment. */ first_level_valid = tex->b.b.b.nr_samples <= 1 && (bpp == 16 || bpp == 32) && tex->tex.macrotile[0]; if (SCREEN_DBG_ON(rscreen, DBG_NO_CBZB)) first_level_valid = FALSE; for (i = 0; i <= tex->b.b.b.last_level; i++) tex->tex.cbzb_allowed[i] = first_level_valid && tex->tex.macrotile[i]; }
boolean r300_texture_desc_init(struct r300_screen *rscreen, struct r300_resource *tex, const struct pipe_resource *base) { tex->b.b.b.target = base->target; tex->b.b.b.format = base->format; tex->b.b.b.width0 = base->width0; tex->b.b.b.height0 = base->height0; tex->b.b.b.depth0 = base->depth0; tex->b.b.b.array_size = base->array_size; tex->b.b.b.last_level = base->last_level; tex->b.b.b.nr_samples = base->nr_samples; tex->tex.width0 = base->width0; tex->tex.height0 = base->height0; tex->tex.depth0 = base->depth0; r300_setup_flags(tex); /* Align a 3D NPOT texture to POT. */ if (base->target == PIPE_TEXTURE_3D && tex->tex.is_npot) { tex->tex.width0 = util_next_power_of_two(tex->tex.width0); tex->tex.height0 = util_next_power_of_two(tex->tex.height0); tex->tex.depth0 = util_next_power_of_two(tex->tex.depth0); } /* Setup tiling. */ if (tex->tex.microtile == RADEON_LAYOUT_UNKNOWN) { r300_setup_tiling(rscreen, tex); } r300_setup_cbzb_flags(rscreen, tex); /* Setup the miptree description. */ r300_setup_miptree(rscreen, tex, TRUE); /* If the required buffer size is larger the given max size, * try again without the alignment for the CBZB clear. */ if (tex->buf_size && tex->tex.size_in_bytes > tex->buf_size) { r300_setup_miptree(rscreen, tex, FALSE); } r300_setup_hyperz_properties(rscreen, tex); if (tex->buf_size) { /* Make sure the buffer we got is large enough. */ if (tex->tex.size_in_bytes > tex->buf_size) { fprintf(stderr, "r300: texture_desc_init: The buffer is not " "large enough. Got: %i, Need: %i, Info:\n", tex->buf_size, tex->tex.size_in_bytes); r300_tex_print_info(tex, "texture_desc_init"); return FALSE; } tex->tex.buffer_size_in_bytes = tex->buf_size; } else { tex->tex.buffer_size_in_bytes = tex->tex.size_in_bytes; } if (SCREEN_DBG_ON(rscreen, DBG_TEX)) r300_tex_print_info(tex, "texture_desc_init"); return TRUE; }
void r300_texture_desc_init(struct r300_screen *rscreen, struct r300_resource *tex, const struct pipe_resource *base) { tex->b.b.target = base->target; tex->b.b.format = base->format; tex->b.b.width0 = base->width0; tex->b.b.height0 = base->height0; tex->b.b.depth0 = base->depth0; tex->b.b.array_size = base->array_size; tex->b.b.last_level = base->last_level; tex->b.b.nr_samples = base->nr_samples; tex->tex.width0 = base->width0; tex->tex.height0 = base->height0; tex->tex.depth0 = base->depth0; /* There is a CB memory addressing hardware bug that limits the width * of the MSAA buffer in some cases in R520. In order to get around it, * the following code lowers the sample count depending on the format and * the width. * * The only catch is that all MSAA colorbuffers and a zbuffer which are * supposed to be used together should always be bound together. Only * then the correct minimum sample count of all bound buffers is used * for rendering. */ if (rscreen->caps.is_r500) { /* FP16 6x MSAA buffers are limited to a width of 1360 pixels. */ if ((tex->b.b.format == PIPE_FORMAT_R16G16B16A16_FLOAT || tex->b.b.format == PIPE_FORMAT_R16G16B16X16_FLOAT) && tex->b.b.nr_samples == 6 && tex->b.b.width0 > 1360) { tex->b.b.nr_samples = 4; } /* FP16 4x MSAA buffers are limited to a width of 2048 pixels. */ if ((tex->b.b.format == PIPE_FORMAT_R16G16B16A16_FLOAT || tex->b.b.format == PIPE_FORMAT_R16G16B16X16_FLOAT) && tex->b.b.nr_samples == 4 && tex->b.b.width0 > 2048) { tex->b.b.nr_samples = 2; } } /* 32-bit 6x MSAA buffers are limited to a width of 2720 pixels. * This applies to all R300-R500 cards. */ if (util_format_get_blocksizebits(tex->b.b.format) == 32 && !util_format_is_depth_or_stencil(tex->b.b.format) && tex->b.b.nr_samples == 6 && tex->b.b.width0 > 2720) { tex->b.b.nr_samples = 4; } r300_setup_flags(tex); /* Align a 3D NPOT texture to POT. */ if (base->target == PIPE_TEXTURE_3D && tex->tex.is_npot) { tex->tex.width0 = util_next_power_of_two(tex->tex.width0); tex->tex.height0 = util_next_power_of_two(tex->tex.height0); tex->tex.depth0 = util_next_power_of_two(tex->tex.depth0); } /* Setup tiling. */ if (tex->tex.microtile == RADEON_LAYOUT_UNKNOWN) { r300_setup_tiling(rscreen, tex); } r300_setup_cbzb_flags(rscreen, tex); /* Setup the miptree description. */ r300_setup_miptree(rscreen, tex, TRUE); /* If the required buffer size is larger than the given max size, * try again without the alignment for the CBZB clear. */ if (tex->buf && tex->tex.size_in_bytes > tex->buf->size) { r300_setup_miptree(rscreen, tex, FALSE); /* Make sure the buffer we got is large enough. */ if (tex->tex.size_in_bytes > tex->buf->size) { fprintf(stderr, "r300: I got a pre-allocated buffer to use it as a texture " "storage, but the buffer is too small. I'll use the buffer " "anyway, because I can't crash here, but it's dangerous. " "This can be a DDX bug. Got: %iB, Need: %iB, Info:\n", tex->buf->size, tex->tex.size_in_bytes); r300_tex_print_info(tex, "texture_desc_init"); /* Ooops, what now. Apps will break if we fail this, * so just pretend everything's okay. */ } } r300_setup_hyperz_properties(rscreen, tex); r300_setup_cmask_properties(rscreen, tex); if (SCREEN_DBG_ON(rscreen, DBG_TEX)) r300_tex_print_info(tex, "texture_desc_init"); }