/** * Return the base format just like _mesa_base_fbo_format does. */ static GLenum st_pipe_format_to_base_format(enum pipe_format format) { GLenum base_format; if (util_format_is_depth_or_stencil(format)) { if (util_format_is_depth_and_stencil(format)) { base_format = GL_DEPTH_STENCIL; } else { if (format == PIPE_FORMAT_S8_USCALED) base_format = GL_STENCIL_INDEX; else base_format = GL_DEPTH_COMPONENT; } } else { /* is this enough? */ if (util_format_has_alpha(format)) base_format = GL_RGBA; else base_format = GL_RGB; } return base_format; }
/** * Specify the surface to cache. */ void sp_tile_cache_set_surface(struct softpipe_tile_cache *tc, struct pipe_surface *ps) { struct pipe_context *pipe = tc->pipe; if (tc->transfer) { if (ps == tc->surface) return; if (tc->transfer_map) { pipe->transfer_unmap(pipe, tc->transfer); tc->transfer_map = NULL; } pipe->transfer_destroy(pipe, tc->transfer); tc->transfer = NULL; } tc->surface = ps; if (ps) { tc->transfer = pipe_get_transfer(pipe, ps->texture, ps->u.tex.level, ps->u.tex.first_layer, PIPE_TRANSFER_READ_WRITE | PIPE_TRANSFER_UNSYNCHRONIZED, 0, 0, ps->width, ps->height); tc->depth_stencil = util_format_is_depth_or_stencil(ps->format); } }
/** * Optimal hardware path for blitting pixels. * Scaling, format conversion, up- and downsampling (resolve) are allowed. */ static void fd_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info) { struct fd_context *ctx = fd_context(pctx); struct pipe_blit_info info = *blit_info; if (info.src.resource->nr_samples > 1 && info.dst.resource->nr_samples <= 1 && !util_format_is_depth_or_stencil(info.src.resource->format) && !util_format_is_pure_integer(info.src.resource->format)) { DBG("color resolve unimplemented"); return; } if (util_try_blit_via_copy_region(pctx, &info)) { return; /* done */ } if (info.mask & PIPE_MASK_S) { DBG("cannot blit stencil, skipping"); info.mask &= ~PIPE_MASK_S; } if (!util_blitter_is_blit_supported(ctx->blitter, &info)) { DBG("blit unsupported %s -> %s", util_format_short_name(info.src.resource->format), util_format_short_name(info.dst.resource->format)); return; } fd_blitter_pipe_begin(ctx); util_blitter_blit(ctx->blitter, &info); fd_blitter_pipe_end(ctx); }
static unsigned get_texture_format_swizzle(const struct st_context *st, const struct st_texture_object *stObj, unsigned glsl_version) { GLenum baseFormat = _mesa_texture_base_format(&stObj->base); unsigned tex_swizzle; if (baseFormat != GL_NONE) { GLenum depth_mode = stObj->base.DepthMode; /* In ES 3.0, DEPTH_TEXTURE_MODE is expected to be GL_RED for textures * with depth component data specified with a sized internal format. */ if (_mesa_is_gles3(st->ctx) && util_format_is_depth_or_stencil(stObj->pt->format)) { const struct gl_texture_image *firstImage = _mesa_base_tex_image(&stObj->base); if (firstImage->InternalFormat != GL_DEPTH_COMPONENT && firstImage->InternalFormat != GL_DEPTH_STENCIL && firstImage->InternalFormat != GL_STENCIL_INDEX) depth_mode = GL_RED; } tex_swizzle = compute_texture_format_swizzle(baseFormat, depth_mode, stObj->pt->format, glsl_version); } else { tex_swizzle = SWIZZLE_XYZW; } /* Combine the texture format swizzle with user's swizzle */ return swizzle_swizzle(stObj->base._Swizzle, tex_swizzle); }
static void r300_texture_setup_fb_state(struct r300_screen* screen, struct r300_texture* tex) { unsigned i; /* Set framebuffer state. */ if (util_format_is_depth_or_stencil(tex->desc.b.b.format)) { for (i = 0; i <= tex->desc.b.b.last_level; i++) { tex->fb_state.pitch[i] = tex->desc.stride_in_pixels[i] | R300_DEPTHMACROTILE(tex->desc.macrotile[i]) | R300_DEPTHMICROTILE(tex->desc.microtile); } tex->fb_state.format = r300_translate_zsformat(tex->desc.b.b.format); } else { for (i = 0; i <= tex->desc.b.b.last_level; i++) { tex->fb_state.pitch[i] = tex->desc.stride_in_pixels[i] | r300_translate_colorformat(tex->desc.b.b.format) | R300_COLOR_TILE(tex->desc.macrotile[i]) | R300_COLOR_MICROTILE(tex->desc.microtile); } tex->fb_state.format = r300_translate_out_fmt(tex->desc.b.b.format); } }
static void si_blit(struct pipe_context *ctx, const struct pipe_blit_info *info) { struct r600_context *rctx = (struct r600_context*)ctx; if (info->src.resource->nr_samples > 1 && info->dst.resource->nr_samples <= 1 && !util_format_is_depth_or_stencil(info->src.resource->format) && !util_format_is_pure_integer(info->src.resource->format)) { si_msaa_color_resolve(ctx, info); return; } assert(util_blitter_is_blit_supported(rctx->blitter, info)); /* The driver doesn't decompress resources automatically while * u_blitter is rendering. */ r600_decompress_subresource(ctx, info->src.resource, info->src.level, info->src.box.z, info->src.box.z + info->src.box.depth - 1); r600_blitter_begin(ctx, R600_BLIT); util_blitter_blit(rctx->blitter, info); r600_blitter_end(ctx); }
/** * Specify the surface to cache. */ void sp_tile_cache_set_surface(struct softpipe_tile_cache *tc, struct pipe_surface *ps) { struct pipe_context *pipe = tc->pipe; if (tc->transfer_map) { if (ps == tc->surface) return; pipe->transfer_unmap(pipe, tc->transfer); tc->transfer = NULL; tc->transfer_map = NULL; } tc->surface = ps; if (ps) { if (ps->texture->target != PIPE_BUFFER) { tc->transfer_map = pipe_transfer_map(pipe, ps->texture, ps->u.tex.level, ps->u.tex.first_layer, PIPE_TRANSFER_READ_WRITE | PIPE_TRANSFER_UNSYNCHRONIZED, 0, 0, ps->width, ps->height, &tc->transfer); } else { /* can't render to buffers */ assert(0); } tc->depth_stencil = util_format_is_depth_or_stencil(ps->format); } }
static void si_blit(struct pipe_context *ctx, const struct pipe_blit_info *info) { struct r600_context *rctx = (struct r600_context*)ctx; struct r600_resource_texture *rsrc = (struct r600_resource_texture*)info->src.resource; assert(util_blitter_is_blit_supported(rctx->blitter, info)); if (info->src.resource->nr_samples > 1 && info->dst.resource->nr_samples <= 1 && !util_format_is_depth_or_stencil(info->src.resource->format) && !util_format_is_pure_integer(info->src.resource->format)) { debug_printf("radeonsi: color resolve is unimplemented\n"); return; } if (rsrc->is_depth && !rsrc->is_flushing_texture) { si_blit_decompress_depth_in_place(rctx, rsrc, info->src.level, info->src.level, info->src.box.z, info->src.box.z + info->src.box.depth - 1); } r600_blitter_begin(ctx, R600_BLIT); util_blitter_blit(rctx->blitter, info); r600_blitter_end(ctx); }
static int r600_setup_surface(struct pipe_screen *screen, struct r600_resource_texture *rtex, unsigned array_mode, unsigned pitch_in_bytes_override) { struct r600_screen *rscreen = (struct r600_screen*)screen; int r; if (util_format_is_depth_or_stencil(rtex->real_format)) { rtex->surface.flags |= RADEON_SURF_ZBUFFER; rtex->surface.flags |= RADEON_SURF_SBUFFER; } r = rscreen->ws->surface_init(rscreen->ws, &rtex->surface); if (r) { return r; } if (pitch_in_bytes_override && pitch_in_bytes_override != rtex->surface.level[0].pitch_bytes) { /* old ddx on evergreen over estimate alignment for 1d, only 1 level * for those */ rtex->surface.level[0].nblk_x = pitch_in_bytes_override / rtex->surface.bpe; rtex->surface.level[0].pitch_bytes = pitch_in_bytes_override; rtex->surface.level[0].slice_size = pitch_in_bytes_override * rtex->surface.level[0].nblk_y; if (rtex->surface.flags & RADEON_SURF_SBUFFER) { rtex->surface.stencil_offset = rtex->surface.level[0].slice_size; } } return 0; }
static void svga_blit(struct pipe_context *pipe, const struct pipe_blit_info *blit_info) { struct svga_context *svga = svga_context(pipe); struct pipe_blit_info info = *blit_info; if (info.src.resource->nr_samples > 1 && info.dst.resource->nr_samples <= 1 && !util_format_is_depth_or_stencil(info.src.resource->format) && !util_format_is_pure_integer(info.src.resource->format)) { debug_printf("svga: color resolve unimplemented\n"); return; } if (util_try_blit_via_copy_region(pipe, &info)) { return; /* done */ } if (info.mask & PIPE_MASK_S) { debug_printf("svga: cannot blit stencil, skipping\n"); info.mask &= ~PIPE_MASK_S; } if (!util_blitter_is_blit_supported(svga->blitter, &info)) { debug_printf("svga: blit unsupported %s -> %s\n", util_format_short_name(info.src.resource->format), util_format_short_name(info.dst.resource->format)); return; } /* XXX turn off occlusion and streamout queries */ util_blitter_save_vertex_buffers(svga->blitter, svga->curr.num_vertex_buffers, svga->curr.vb); util_blitter_save_vertex_elements(svga->blitter, (void*)svga->curr.velems); util_blitter_save_vertex_shader(svga->blitter, svga->curr.vs); /*util_blitter_save_geometry_shader(svga->blitter, svga->curr.gs);*/ /*util_blitter_save_so_targets(svga->blitter, svga->num_so_targets, (struct pipe_stream_output_target**)svga->so_targets);*/ util_blitter_save_rasterizer(svga->blitter, (void*)svga->curr.rast); util_blitter_save_viewport(svga->blitter, &svga->curr.viewport); util_blitter_save_scissor(svga->blitter, &svga->curr.scissor); util_blitter_save_fragment_shader(svga->blitter, svga->curr.fs); util_blitter_save_blend(svga->blitter, (void*)svga->curr.blend); util_blitter_save_depth_stencil_alpha(svga->blitter, (void*)svga->curr.depth); util_blitter_save_stencil_ref(svga->blitter, &svga->curr.stencil_ref); /*util_blitter_save_sample_mask(svga->blitter, svga->sample_mask);*/ util_blitter_save_framebuffer(svga->blitter, &svga->curr.framebuffer); util_blitter_save_fragment_sampler_states(svga->blitter, svga->curr.num_samplers, (void**)svga->curr.sampler); util_blitter_save_fragment_sampler_views(svga->blitter, svga->curr.num_sampler_views, svga->curr.sampler_views); /*util_blitter_save_render_condition(svga->blitter, svga->render_cond_query, svga->render_cond_mode);*/ util_blitter_blit(svga->blitter, &info); }
static void lp_blit(struct pipe_context *pipe, const struct pipe_blit_info *blit_info) { struct llvmpipe_context *lp = llvmpipe_context(pipe); struct pipe_blit_info info = *blit_info; if (info.src.resource->nr_samples > 1 && info.dst.resource->nr_samples <= 1 && !util_format_is_depth_or_stencil(info.src.resource->format) && !util_format_is_pure_integer(info.src.resource->format)) { debug_printf("llvmpipe: color resolve unimplemented\n"); return; } if (util_try_blit_via_copy_region(pipe, &info)) { return; /* done */ } if (info.mask & PIPE_MASK_S) { debug_printf("llvmpipe: cannot blit stencil, skipping\n"); info.mask &= ~PIPE_MASK_S; } if (!util_blitter_is_blit_supported(lp->blitter, &info)) { debug_printf("llvmpipe: blit unsupported %s -> %s\n", util_format_short_name(info.src.resource->format), util_format_short_name(info.dst.resource->format)); return; } /* XXX turn off occlusion and streamout queries */ util_blitter_save_vertex_buffers(lp->blitter, lp->num_vertex_buffers, lp->vertex_buffer); util_blitter_save_vertex_elements(lp->blitter, (void*)lp->velems); util_blitter_save_vertex_shader(lp->blitter, (void*)lp->vs); util_blitter_save_geometry_shader(lp->blitter, (void*)lp->gs); /*util_blitter_save_so_targets(lp->blitter, lp->num_so_targets, (struct pipe_stream_output_target**)lp->so_targets);*/ util_blitter_save_rasterizer(lp->blitter, (void*)lp->rasterizer); util_blitter_save_viewport(lp->blitter, &lp->viewport); util_blitter_save_scissor(lp->blitter, &lp->scissor); util_blitter_save_fragment_shader(lp->blitter, lp->fs); util_blitter_save_blend(lp->blitter, (void*)lp->blend); util_blitter_save_depth_stencil_alpha(lp->blitter, (void*)lp->depth_stencil); util_blitter_save_stencil_ref(lp->blitter, &lp->stencil_ref); /*util_blitter_save_sample_mask(sp->blitter, lp->sample_mask);*/ util_blitter_save_framebuffer(lp->blitter, &lp->framebuffer); util_blitter_save_fragment_sampler_states(lp->blitter, lp->num_samplers[PIPE_SHADER_FRAGMENT], (void**)lp->samplers[PIPE_SHADER_FRAGMENT]); util_blitter_save_fragment_sampler_views(lp->blitter, lp->num_sampler_views[PIPE_SHADER_FRAGMENT], lp->sampler_views[PIPE_SHADER_FRAGMENT]); util_blitter_save_render_condition(lp->blitter, lp->render_cond_query, lp->render_cond_mode); util_blitter_blit(lp->blitter, &info); }
static unsigned r600_choose_tiling(struct r600_common_screen *rscreen, const struct pipe_resource *templ) { const struct util_format_description *desc = util_format_description(templ->format); /* MSAA resources must be 2D tiled. */ if (templ->nr_samples > 1) return RADEON_SURF_MODE_2D; /* Transfer resources should be linear. */ if (templ->flags & R600_RESOURCE_FLAG_TRANSFER) return RADEON_SURF_MODE_LINEAR_ALIGNED; /* Handle common candidates for the linear mode. * Compressed textures must always be tiled. */ if (!(templ->flags & R600_RESOURCE_FLAG_FORCE_TILING) && !util_format_is_compressed(templ->format)) { /* Not everything can be linear, so we cannot enforce it * for all textures. */ if ((rscreen->debug_flags & DBG_NO_TILING) && (!util_format_is_depth_or_stencil(templ->format) || !(templ->flags & R600_RESOURCE_FLAG_FLUSHED_DEPTH))) return RADEON_SURF_MODE_LINEAR_ALIGNED; /* Tiling doesn't work with the 422 (SUBSAMPLED) formats on R600+. */ if (desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED) return RADEON_SURF_MODE_LINEAR_ALIGNED; /* Cursors are linear on SI. * (XXX double-check, maybe also use RADEON_SURF_SCANOUT) */ if (rscreen->chip_class >= SI && (templ->bind & PIPE_BIND_CURSOR)) return RADEON_SURF_MODE_LINEAR_ALIGNED; if (templ->bind & PIPE_BIND_LINEAR) return RADEON_SURF_MODE_LINEAR_ALIGNED; /* Textures with a very small height are recommended to be linear. */ if (templ->target == PIPE_TEXTURE_1D || templ->target == PIPE_TEXTURE_1D_ARRAY || templ->height0 <= 4) return RADEON_SURF_MODE_LINEAR_ALIGNED; /* Textures likely to be mapped often. */ if (templ->usage == PIPE_USAGE_STAGING || templ->usage == PIPE_USAGE_STREAM) return RADEON_SURF_MODE_LINEAR_ALIGNED; } /* Make small textures 1D tiled. */ if (templ->width0 <= 16 || templ->height0 <= 16 || (rscreen->debug_flags & DBG_NO_2D_TILING)) return RADEON_SURF_MODE_1D; /* The allocator will switch to 1D if needed. */ return RADEON_SURF_MODE_2D; }
static bool do_hardware_msaa_resolve(struct pipe_context *ctx, const struct pipe_blit_info *info) { struct si_context *sctx = (struct si_context*)ctx; struct r600_texture *dst = (struct r600_texture*)info->dst.resource; unsigned dst_width = u_minify(info->dst.resource->width0, info->dst.level); unsigned dst_height = u_minify(info->dst.resource->height0, info->dst.level); enum pipe_format format = int_to_norm_format(info->dst.format); unsigned sample_mask = ~0; /* Hardware MSAA resolve doesn't work if SPI format = NORM16_ABGR and * the format is R16G16. Use R16A16, which does work. */ if (format == PIPE_FORMAT_R16G16_UNORM) format = PIPE_FORMAT_R16A16_UNORM; if (format == PIPE_FORMAT_R16G16_SNORM) format = PIPE_FORMAT_R16A16_SNORM; if (info->src.resource->nr_samples > 1 && info->dst.resource->nr_samples <= 1 && util_max_layer(info->src.resource, 0) == 0 && util_max_layer(info->dst.resource, info->dst.level) == 0 && util_is_format_compatible(util_format_description(info->src.format), util_format_description(info->dst.format)) && !util_format_is_pure_integer(format) && !util_format_is_depth_or_stencil(format) && !info->scissor_enable && (info->mask & PIPE_MASK_RGBA) == PIPE_MASK_RGBA && dst_width == info->src.resource->width0 && dst_height == info->src.resource->height0 && info->dst.box.x == 0 && info->dst.box.y == 0 && info->dst.box.width == dst_width && info->dst.box.height == dst_height && info->dst.box.depth == 1 && info->src.box.x == 0 && info->src.box.y == 0 && info->src.box.width == dst_width && info->src.box.height == dst_height && info->src.box.depth == 1 && dst->surface.level[info->dst.level].mode >= RADEON_SURF_MODE_1D && !(dst->surface.flags & RADEON_SURF_SCANOUT) && (!dst->cmask.size || !dst->dirty_level_mask) && /* dst cannot be fast-cleared */ !dst->dcc_offset) { si_blitter_begin(ctx, SI_COLOR_RESOLVE | (info->render_condition_enable ? 0 : SI_DISABLE_RENDER_COND)); util_blitter_custom_resolve_color(sctx->blitter, info->dst.resource, info->dst.level, info->dst.box.z, info->src.resource, info->src.box.z, sample_mask, sctx->custom_blend_resolve, format); si_blitter_end(ctx); return true; } return false; }
static struct r600_resource_texture * r600_texture_create_object(struct pipe_screen *screen, const struct pipe_resource *base, unsigned array_mode, unsigned pitch_in_bytes_override, unsigned max_buffer_size, struct pb_buffer *buf, boolean alloc_bo, struct radeon_surface *surface) { struct r600_resource_texture *rtex; struct si_resource *resource; struct r600_screen *rscreen = (struct r600_screen*)screen; int r; rtex = CALLOC_STRUCT(r600_resource_texture); if (rtex == NULL) return NULL; resource = &rtex->resource; resource->b.b = *base; resource->b.vtbl = &r600_texture_vtbl; pipe_reference_init(&resource->b.b.reference, 1); resource->b.b.screen = screen; rtex->pitch_override = pitch_in_bytes_override; rtex->real_format = base->format; /* only mark depth textures the HW can hit as depth textures */ if (util_format_is_depth_or_stencil(rtex->real_format) && permit_hardware_blit(screen, base)) rtex->depth = 1; r600_setup_miptree(screen, rtex, array_mode); rtex->surface = *surface; r = r600_setup_surface(screen, rtex, array_mode, pitch_in_bytes_override); if (r) { FREE(rtex); return NULL; } /* Now create the backing buffer. */ if (!buf && alloc_bo) { struct pipe_resource *ptex = &rtex->resource.b.b; unsigned base_align = r600_get_base_alignment(screen, ptex->format, array_mode); base_align = rtex->surface.bo_alignment; if (!r600_init_resource(rscreen, resource, rtex->size, base_align, base->bind, base->usage)) { FREE(rtex); return NULL; } } else if (buf) { resource->buf = buf; resource->cs_buf = rscreen->ws->buffer_get_cs_handle(buf); resource->domains = RADEON_DOMAIN_GTT | RADEON_DOMAIN_VRAM; } return rtex; }
static void r300_blit(struct pipe_context *pipe, const struct pipe_blit_info *blit) { struct r300_context *r300 = r300_context(pipe); struct pipe_framebuffer_state *fb = (struct pipe_framebuffer_state*)r300->fb_state.state; struct pipe_blit_info info = *blit; /* MSAA resolve. */ if (info.src.resource->nr_samples > 1 && !util_format_is_depth_or_stencil(info.src.resource->format)) { r300_msaa_resolve(pipe, &info); return; } /* Can't read MSAA textures. */ if (info.src.resource->nr_samples > 1) { return; } /* Blit a combined depth-stencil resource as color. * S8Z24 is the only supported stencil format. */ if ((info.mask & PIPE_MASK_S) && info.src.format == PIPE_FORMAT_S8_UINT_Z24_UNORM && info.dst.format == PIPE_FORMAT_S8_UINT_Z24_UNORM) { if (info.dst.resource->nr_samples > 1) { /* Cannot do that with MSAA buffers. */ info.mask &= ~PIPE_MASK_S; if (!(info.mask & PIPE_MASK_Z)) { return; } } else { /* Single-sample buffer. */ info.src.format = PIPE_FORMAT_B8G8R8A8_UNORM; info.dst.format = PIPE_FORMAT_B8G8R8A8_UNORM; if (info.mask & PIPE_MASK_Z) { info.mask = PIPE_MASK_RGBA; /* depth+stencil */ } else { info.mask = PIPE_MASK_B; /* stencil only */ } } } /* Decompress ZMASK. */ if (r300->zmask_in_use && !r300->locked_zbuffer) { if (fb->zsbuf->texture == info.src.resource || fb->zsbuf->texture == info.dst.resource) { r300_decompress_zmask(r300); } } r300_blitter_begin(r300, R300_BLIT | (info.render_condition_enable ? 0 : R300_IGNORE_RENDER_COND)); util_blitter_blit(r300->blitter, &info); r300_blitter_end(r300); }
static void r300_setup_tiling(struct r300_screen *screen, struct r300_resource *tex) { enum pipe_format format = tex->b.b.format; boolean rv350_mode = screen->caps.family >= CHIP_R350; boolean is_zb = util_format_is_depth_or_stencil(format); boolean dbg_no_tiling = SCREEN_DBG_ON(screen, DBG_NO_TILING); boolean force_microtiling = (tex->b.b.flags & R300_RESOURCE_FORCE_MICROTILING) != 0; if (tex->b.b.nr_samples > 1) { tex->tex.microtile = RADEON_LAYOUT_TILED; tex->tex.macrotile[0] = RADEON_LAYOUT_TILED; return; } tex->tex.microtile = RADEON_LAYOUT_LINEAR; tex->tex.macrotile[0] = RADEON_LAYOUT_LINEAR; if (tex->b.b.usage == PIPE_USAGE_STAGING) { return; } if (!util_format_is_plain(format)) { return; } /* If height == 1, disable microtiling except for zbuffer. */ if (!force_microtiling && !is_zb && (tex->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; } }
void nv30_blit(struct pipe_context *pipe, const struct pipe_blit_info *blit_info) { struct nv30_context *nv30 = nv30_context(pipe); struct pipe_blit_info info = *blit_info; if (info.src.resource->nr_samples > 1 && info.dst.resource->nr_samples <= 1 && !util_format_is_depth_or_stencil(info.src.resource->format) && !util_format_is_pure_integer(info.src.resource->format)) { debug_printf("nv30: color resolve unimplemented\n"); return; } if (util_try_blit_via_copy_region(pipe, &info)) { return; /* done */ } if (info.mask & PIPE_MASK_S) { debug_printf("nv30: cannot blit stencil, skipping\n"); info.mask &= ~PIPE_MASK_S; } if (!util_blitter_is_blit_supported(nv30->blitter, &info)) { debug_printf("nv30: blit unsupported %s -> %s\n", util_format_short_name(info.src.resource->format), util_format_short_name(info.dst.resource->format)); return; } /* XXX turn off occlusion queries */ util_blitter_save_vertex_buffer_slot(nv30->blitter, nv30->vtxbuf); util_blitter_save_vertex_elements(nv30->blitter, nv30->vertex); util_blitter_save_vertex_shader(nv30->blitter, nv30->vertprog.program); util_blitter_save_rasterizer(nv30->blitter, nv30->rast); util_blitter_save_viewport(nv30->blitter, &nv30->viewport); util_blitter_save_scissor(nv30->blitter, &nv30->scissor); util_blitter_save_fragment_shader(nv30->blitter, nv30->fragprog.program); util_blitter_save_blend(nv30->blitter, nv30->blend); util_blitter_save_depth_stencil_alpha(nv30->blitter, nv30->zsa); util_blitter_save_stencil_ref(nv30->blitter, &nv30->stencil_ref); util_blitter_save_sample_mask(nv30->blitter, nv30->sample_mask); util_blitter_save_framebuffer(nv30->blitter, &nv30->framebuffer); util_blitter_save_fragment_sampler_states(nv30->blitter, nv30->fragprog.num_samplers, (void**)nv30->fragprog.samplers); util_blitter_save_fragment_sampler_views(nv30->blitter, nv30->fragprog.num_textures, nv30->fragprog.textures); util_blitter_save_render_condition(nv30->blitter, nv30->render_cond_query, nv30->render_cond_mode); util_blitter_blit(nv30->blitter, &info); }
static boolean nvc0_screen_is_format_supported(struct pipe_screen *pscreen, enum pipe_format format, enum pipe_texture_target target, unsigned sample_count, unsigned bindings) { const struct util_format_description *desc = util_format_description(format); if (sample_count > 8) return false; if (!(0x117 & (1 << sample_count))) /* 0, 1, 2, 4 or 8 */ return false; /* Short-circuit the rest of the logic -- this is used by the state tracker * to determine valid MS levels in a no-attachments scenario. */ if (format == PIPE_FORMAT_NONE && bindings & PIPE_BIND_RENDER_TARGET) return true; if (!util_format_is_supported(format, bindings)) return false; if ((bindings & PIPE_BIND_SAMPLER_VIEW) && (target != PIPE_BUFFER)) if (util_format_get_blocksizebits(format) == 3 * 32) return false; if (bindings & PIPE_BIND_LINEAR) if (util_format_is_depth_or_stencil(format) || (target != PIPE_TEXTURE_1D && target != PIPE_TEXTURE_2D && target != PIPE_TEXTURE_RECT) || sample_count > 1) return false; /* Restrict ETC2 and ASTC formats here. These are only supported on GK20A. */ if ((desc->layout == UTIL_FORMAT_LAYOUT_ETC || desc->layout == UTIL_FORMAT_LAYOUT_ASTC) && /* The claim is that this should work on GM107 but it doesn't. Need to * test further and figure out if it's a nouveau issue or a HW one. nouveau_screen(pscreen)->class_3d < GM107_3D_CLASS && */ nouveau_screen(pscreen)->class_3d != NVEA_3D_CLASS) return false; /* transfers & shared are always supported */ bindings &= ~(PIPE_BIND_TRANSFER_READ | PIPE_BIND_TRANSFER_WRITE | PIPE_BIND_LINEAR | PIPE_BIND_SHARED); return (( nvc0_format_table[format].usage | nvc0_vertex_format[format].usage) & bindings) == bindings; }
static void sp_blit(struct pipe_context *pipe, const struct pipe_blit_info *info) { struct softpipe_context *sp = softpipe_context(pipe); if (info->render_condition_enable && !softpipe_check_render_cond(sp)) return; if (info->src.resource->nr_samples > 1 && info->dst.resource->nr_samples <= 1 && !util_format_is_depth_or_stencil(info->src.resource->format) && !util_format_is_pure_integer(info->src.resource->format)) { debug_printf("softpipe: color resolve unimplemented\n"); return; } if (util_try_blit_via_copy_region(pipe, info)) { return; /* done */ } if (!util_blitter_is_blit_supported(sp->blitter, info)) { debug_printf("softpipe: blit unsupported %s -> %s\n", util_format_short_name(info->src.resource->format), util_format_short_name(info->dst.resource->format)); return; } /* XXX turn off occlusion and streamout queries */ util_blitter_save_vertex_buffer_slot(sp->blitter, sp->vertex_buffer); util_blitter_save_vertex_elements(sp->blitter, sp->velems); util_blitter_save_vertex_shader(sp->blitter, sp->vs); util_blitter_save_geometry_shader(sp->blitter, sp->gs); util_blitter_save_so_targets(sp->blitter, sp->num_so_targets, (struct pipe_stream_output_target**)sp->so_targets); util_blitter_save_rasterizer(sp->blitter, sp->rasterizer); util_blitter_save_viewport(sp->blitter, &sp->viewports[0]); util_blitter_save_scissor(sp->blitter, &sp->scissors[0]); util_blitter_save_fragment_shader(sp->blitter, sp->fs); util_blitter_save_blend(sp->blitter, sp->blend); util_blitter_save_depth_stencil_alpha(sp->blitter, sp->depth_stencil); util_blitter_save_stencil_ref(sp->blitter, &sp->stencil_ref); /*util_blitter_save_sample_mask(sp->blitter, sp->sample_mask);*/ util_blitter_save_framebuffer(sp->blitter, &sp->framebuffer); util_blitter_save_fragment_sampler_states(sp->blitter, sp->num_samplers[PIPE_SHADER_FRAGMENT], (void**)sp->samplers[PIPE_SHADER_FRAGMENT]); util_blitter_save_fragment_sampler_views(sp->blitter, sp->num_sampler_views[PIPE_SHADER_FRAGMENT], sp->sampler_views[PIPE_SHADER_FRAGMENT]); util_blitter_save_render_condition(sp->blitter, sp->render_cond_query, sp->render_cond_cond, sp->render_cond_mode); util_blitter_blit(sp->blitter, info); }
static int r600_setup_surface(struct pipe_screen *screen, struct r600_resource_texture *rtex, unsigned array_mode, unsigned pitch_in_bytes_override) { struct pipe_resource *ptex = &rtex->resource.b.b; struct r600_screen *rscreen = (struct r600_screen*)screen; unsigned i; int r; if (util_format_is_depth_or_stencil(rtex->real_format)) { rtex->surface.flags |= RADEON_SURF_ZBUFFER; rtex->surface.flags |= RADEON_SURF_SBUFFER; } r = rscreen->ws->surface_init(rscreen->ws, &rtex->surface); if (r) { return r; } rtex->size = rtex->surface.bo_size; if (pitch_in_bytes_override && pitch_in_bytes_override != rtex->surface.level[0].pitch_bytes) { /* old ddx on evergreen over estimate alignment for 1d, only 1 level * for those */ rtex->surface.level[0].nblk_x = pitch_in_bytes_override / rtex->surface.bpe; rtex->surface.level[0].pitch_bytes = pitch_in_bytes_override; rtex->surface.level[0].slice_size = pitch_in_bytes_override * rtex->surface.level[0].nblk_y; if (rtex->surface.flags & RADEON_SURF_SBUFFER) { rtex->surface.stencil_offset = rtex->surface.level[0].slice_size; } } for (i = 0; i <= ptex->last_level; i++) { rtex->offset[i] = rtex->surface.level[i].offset; rtex->layer_size[i] = rtex->surface.level[i].slice_size; rtex->pitch_in_bytes[i] = rtex->surface.level[i].pitch_bytes; switch (rtex->surface.level[i].mode) { case RADEON_SURF_MODE_LINEAR_ALIGNED: rtex->array_mode[i] = V_009910_ARRAY_LINEAR_ALIGNED; break; case RADEON_SURF_MODE_1D: rtex->array_mode[i] = V_009910_ARRAY_1D_TILED_THIN1; break; case RADEON_SURF_MODE_2D: rtex->array_mode[i] = V_009910_ARRAY_2D_TILED_THIN1; break; default: case RADEON_SURF_MODE_LINEAR: rtex->array_mode[i] = 0; break; } } return 0; }
/* Optimal hardware path for blitting pixels. * Scaling, format conversion, up- and downsampling (resolve) are allowed. */ static void fd_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info) { struct fd_context *ctx = fd_context(pctx); struct pipe_blit_info info = *blit_info; if (info.src.resource->nr_samples > 1 && info.dst.resource->nr_samples <= 1 && !util_format_is_depth_or_stencil(info.src.resource->format) && !util_format_is_pure_integer(info.src.resource->format)) { DBG("color resolve unimplemented"); return; } if (util_try_blit_via_copy_region(pctx, &info)) { return; /* done */ } if (info.mask & PIPE_MASK_S) { DBG("cannot blit stencil, skipping"); info.mask &= ~PIPE_MASK_S; } if (!util_blitter_is_blit_supported(ctx->blitter, &info)) { DBG("blit unsupported %s -> %s", util_format_short_name(info.src.resource->format), util_format_short_name(info.dst.resource->format)); return; } util_blitter_save_vertex_buffer_slot(ctx->blitter, ctx->vertexbuf.vb); util_blitter_save_vertex_elements(ctx->blitter, ctx->vtx); util_blitter_save_vertex_shader(ctx->blitter, ctx->prog.vp); util_blitter_save_rasterizer(ctx->blitter, ctx->rasterizer); util_blitter_save_viewport(ctx->blitter, &ctx->viewport); util_blitter_save_scissor(ctx->blitter, &ctx->scissor); util_blitter_save_fragment_shader(ctx->blitter, ctx->prog.fp); util_blitter_save_blend(ctx->blitter, ctx->blend); util_blitter_save_depth_stencil_alpha(ctx->blitter, ctx->zsa); util_blitter_save_stencil_ref(ctx->blitter, &ctx->stencil_ref); util_blitter_save_sample_mask(ctx->blitter, ctx->sample_mask); util_blitter_save_framebuffer(ctx->blitter, &ctx->framebuffer.base); util_blitter_save_fragment_sampler_states(ctx->blitter, ctx->fragtex.num_samplers, (void **)ctx->fragtex.samplers); util_blitter_save_fragment_sampler_views(ctx->blitter, ctx->fragtex.num_textures, ctx->fragtex.textures); util_blitter_blit(ctx->blitter, &info); }
static void nv50_blit_set_dst(struct nv50_context *nv50, struct pipe_surface *surf, struct nv50_blitctx *blit) { blit->saved.format = surf->format; if (util_format_is_depth_or_stencil(surf->format)) surf->format = nv50_blit_zeta_to_colour_format(surf->format); nv50->framebuffer.cbufs[0] = surf; nv50->framebuffer.nr_cbufs = 1; nv50->framebuffer.zsbuf = NULL; nv50->framebuffer.width = surf->width; nv50->framebuffer.height = surf->height; }
static bool do_hardware_msaa_resolve(struct pipe_context *ctx, const struct pipe_blit_info *info) { struct r600_context *rctx = (struct r600_context*)ctx; struct r600_texture *dst = (struct r600_texture*)info->dst.resource; unsigned dst_width = u_minify(info->dst.resource->width0, info->dst.level); unsigned dst_height = u_minify(info->dst.resource->height0, info->dst.level); enum pipe_format format = int_to_norm_format(info->dst.format); unsigned sample_mask = rctx->b.chip_class == CAYMAN ? ~0 : ((1ull << MAX2(1, info->src.resource->nr_samples)) - 1); if (info->src.resource->nr_samples > 1 && info->dst.resource->nr_samples <= 1 && util_max_layer(info->src.resource, 0) == 0 && util_max_layer(info->dst.resource, info->dst.level) == 0 && info->dst.format == info->src.format && !util_format_is_pure_integer(format) && !util_format_is_depth_or_stencil(format) && !info->scissor_enable && (info->mask & PIPE_MASK_RGBA) == PIPE_MASK_RGBA && dst_width == info->src.resource->width0 && dst_height == info->src.resource->height0 && info->dst.box.x == 0 && info->dst.box.y == 0 && info->dst.box.width == dst_width && info->dst.box.height == dst_height && info->dst.box.depth == 1 && info->src.box.x == 0 && info->src.box.y == 0 && info->src.box.width == dst_width && info->src.box.height == dst_height && info->src.box.depth == 1 && dst->surface.level[info->dst.level].mode >= RADEON_SURF_MODE_1D && (!dst->cmask.size || !dst->dirty_level_mask) /* dst cannot be fast-cleared */) { r600_blitter_begin(ctx, R600_COLOR_RESOLVE | (info->render_condition_enable ? 0 : R600_DISABLE_RENDER_COND)); util_blitter_custom_resolve_color(rctx->blitter, info->dst.resource, info->dst.level, info->dst.box.z, info->src.resource, info->src.box.z, sample_mask, rctx->custom_blend_resolve, format); r600_blitter_end(ctx); return true; } return false; }
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 struct pipe_surface * ilo_create_surface(struct pipe_context *pipe, struct pipe_resource *res, const struct pipe_surface *templ) { const struct ilo_dev_info *dev = ilo_context(pipe)->dev; struct ilo_surface_cso *surf; surf = MALLOC_STRUCT(ilo_surface_cso); assert(surf); surf->base = *templ; pipe_reference_init(&surf->base.reference, 1); surf->base.texture = NULL; pipe_resource_reference(&surf->base.texture, res); surf->base.context = pipe; surf->base.width = u_minify(res->width0, templ->u.tex.level); surf->base.height = u_minify(res->height0, templ->u.tex.level); surf->is_rt = !util_format_is_depth_or_stencil(templ->format); if (surf->is_rt) { /* relax this? */ assert(res->target != PIPE_BUFFER); /* * classic i965 sets render_cache_rw for constant buffers and sol * surfaces but not render buffers. Why? */ ilo_gpe_init_view_surface_for_texture(dev, ilo_texture(res), templ->format, templ->u.tex.level, 1, templ->u.tex.first_layer, templ->u.tex.last_layer - templ->u.tex.first_layer + 1, true, &surf->u.rt); } else { assert(res->target != PIPE_BUFFER); ilo_gpe_init_zs_surface(dev, ilo_texture(res), templ->format, templ->u.tex.level, templ->u.tex.first_layer, templ->u.tex.last_layer - templ->u.tex.first_layer + 1, &surf->u.zs); } return &surf->base; }
static bool do_hardware_msaa_resolve(struct pipe_context *ctx, const struct pipe_blit_info *info) { struct si_context *sctx = (struct si_context*)ctx; struct r600_texture *dst = (struct r600_texture*)info->dst.resource; unsigned dst_width = u_minify(info->dst.resource->width0, info->dst.level); unsigned dst_height = u_minify(info->dst.resource->height0, info->dst.level); enum pipe_format format = int_to_norm_format(info->dst.format); unsigned sample_mask = ~0; if (info->src.resource->nr_samples > 1 && info->dst.resource->nr_samples <= 1 && util_max_layer(info->src.resource, 0) == 0 && util_max_layer(info->dst.resource, info->dst.level) == 0 && info->dst.format == info->src.format && !util_format_is_pure_integer(format) && !util_format_is_depth_or_stencil(format) && !info->scissor_enable && (info->mask & PIPE_MASK_RGBA) == PIPE_MASK_RGBA && dst_width == info->src.resource->width0 && dst_height == info->src.resource->height0 && info->dst.box.x == 0 && info->dst.box.y == 0 && info->dst.box.width == dst_width && info->dst.box.height == dst_height && info->dst.box.depth == 1 && info->src.box.x == 0 && info->src.box.y == 0 && info->src.box.width == dst_width && info->src.box.height == dst_height && info->src.box.depth == 1 && dst->surface.level[info->dst.level].mode >= RADEON_SURF_MODE_1D && !(dst->surface.flags & RADEON_SURF_SCANOUT)) { si_blitter_begin(ctx, SI_COLOR_RESOLVE); util_blitter_custom_resolve_color(sctx->blitter, info->dst.resource, info->dst.level, info->dst.box.z, info->src.resource, info->src.box.z, sample_mask, sctx->custom_blend_resolve, format); si_blitter_end(ctx); return true; } return false; }
void util_blitter_default_dst_texture(struct pipe_surface *dst_templ, struct pipe_resource *dst, unsigned dstlevel, unsigned dstz, const struct pipe_box *srcbox) { memset(dst_templ, 0, sizeof(*dst_templ)); dst_templ->format = dst->format; if (util_format_is_depth_or_stencil(dst->format)) { dst_templ->usage = PIPE_BIND_DEPTH_STENCIL; } else { dst_templ->usage = PIPE_BIND_RENDER_TARGET; } dst_templ->format = util_format_linear(dst->format); dst_templ->u.tex.level = dstlevel; dst_templ->u.tex.first_layer = dstz; dst_templ->u.tex.last_layer = dstz + srcbox->depth - 1; }
struct pipe_resource *r300_texture_from_handle(struct pipe_screen *screen, const struct pipe_resource *base, struct winsys_handle *whandle) { struct r300_winsys_screen *rws = (struct r300_winsys_screen*)screen->winsys; struct r300_screen *rscreen = r300_screen(screen); struct r300_winsys_buffer *buffer; enum r300_buffer_tiling microtile, macrotile; unsigned stride, size; /* Support only 2D textures without mipmaps */ if ((base->target != PIPE_TEXTURE_2D && base->target != PIPE_TEXTURE_RECT) || base->depth0 != 1 || base->last_level != 0) { return NULL; } buffer = rws->buffer_from_handle(rws, whandle, &stride, &size); if (!buffer) return NULL; rws->buffer_get_tiling(rws, buffer, µtile, ¯otile); /* Enforce a microtiled zbuffer. */ if (util_format_is_depth_or_stencil(base->format) && microtile == R300_BUFFER_LINEAR) { switch (util_format_get_blocksize(base->format)) { case 4: microtile = R300_BUFFER_TILED; break; case 2: if (rws->get_value(rws, R300_VID_SQUARE_TILING_SUPPORT)) microtile = R300_BUFFER_SQUARETILED; break; } } return (struct pipe_resource*) r300_texture_create_object(rscreen, base, microtile, macrotile, stride, size, buffer); }
static struct pipe_resource * util_create_texture2d(struct pipe_screen *screen, unsigned width, unsigned height, enum pipe_format format) { struct pipe_resource templ = {{0}}; templ.target = PIPE_TEXTURE_2D; templ.width0 = width; templ.height0 = height; templ.depth0 = 1; templ.array_size = 1; templ.format = format; templ.usage = PIPE_USAGE_DEFAULT; templ.bind = PIPE_BIND_SAMPLER_VIEW | (util_format_is_depth_or_stencil(format) ? PIPE_BIND_DEPTH_STENCIL : PIPE_BIND_RENDER_TARGET); return screen->resource_create(screen, &templ); }
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; } }