enum pipe_texture_target internal_target;
void *vs;
- void *fs[TGSI_WRITEMASK_XYZW + 1];
- void *fs_depth;
+ void *fs[PIPE_MAX_TEXTURE_TYPES][TGSI_WRITEMASK_XYZW + 1];
+ void *fs_depth[PIPE_MAX_TEXTURE_TYPES];
struct pipe_resource *vbuf; /**< quad vertices */
unsigned vbuf_slot;
ctx->cso = cso;
/* disabled blending/masking */
- memset(&ctx->blend, 0, sizeof(ctx->blend));
ctx->blend.rt[0].colormask = PIPE_MASK_RGBA;
/* no-op depth/stencil/alpha */
- memset(&ctx->depthstencil_keep, 0, sizeof(ctx->depthstencil_keep));
- memset(&ctx->depthstencil_write, 0, sizeof(ctx->depthstencil_write));
ctx->depthstencil_write.depth.enabled = 1;
ctx->depthstencil_write.depth.writemask = 1;
ctx->depthstencil_write.depth.func = PIPE_FUNC_ALWAYS;
/* rasterizer */
- memset(&ctx->rasterizer, 0, sizeof(ctx->rasterizer));
ctx->rasterizer.cull_face = PIPE_FACE_NONE;
ctx->rasterizer.gl_rasterization_rules = 1;
ctx->rasterizer.depth_clip = 1;
/* samplers */
- memset(&ctx->sampler, 0, sizeof(ctx->sampler));
ctx->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
ctx->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
ctx->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
ctx->sampler.mag_img_filter = 0; /* set later */
/* vertex elements state */
- memset(&ctx->velem[0], 0, sizeof(ctx->velem[0]) * 2);
for (i = 0; i < 2; i++) {
ctx->velem[i].src_offset = i * 4 * sizeof(float);
ctx->velem[i].instance_divisor = 0;
util_destroy_blit(struct blit_state *ctx)
{
struct pipe_context *pipe = ctx->pipe;
- unsigned i;
+ unsigned i, j;
if (ctx->vs)
pipe->delete_vs_state(pipe, ctx->vs);
- for (i = 0; i < Elements(ctx->fs); i++)
- if (ctx->fs[i])
- pipe->delete_fs_state(pipe, ctx->fs[i]);
+ for (i = 0; i < Elements(ctx->fs); i++) {
+ for (j = 0; j < Elements(ctx->fs[i]); j++) {
+ if (ctx->fs[i][j])
+ pipe->delete_fs_state(pipe, ctx->fs[i][j]);
+ }
+ }
- if (ctx->fs_depth)
- pipe->delete_fs_state(pipe, ctx->fs_depth);
+ for (i = 0; i < Elements(ctx->fs_depth); i++) {
+ if (ctx->fs_depth[i]) {
+ pipe->delete_fs_state(pipe, ctx->fs_depth[i]);
+ }
+ }
pipe_resource_reference(&ctx->vbuf, NULL);
* Helper function to set the fragment shaders.
*/
static INLINE void
-set_fragment_shader(struct blit_state *ctx, uint writemask)
+set_fragment_shader(struct blit_state *ctx, uint writemask,
+ enum pipe_texture_target pipe_tex)
{
- if (!ctx->fs[writemask])
- ctx->fs[writemask] =
- util_make_fragment_tex_shader_writemask(ctx->pipe, TGSI_TEXTURE_2D,
+ if (!ctx->fs[pipe_tex][writemask]) {
+ unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex);
+
+ ctx->fs[pipe_tex][writemask] =
+ util_make_fragment_tex_shader_writemask(ctx->pipe, tgsi_tex,
TGSI_INTERPOLATE_LINEAR,
writemask);
+ }
- cso_set_fragment_shader_handle(ctx->cso, ctx->fs[writemask]);
+ cso_set_fragment_shader_handle(ctx->cso, ctx->fs[pipe_tex][writemask]);
}
* Helper function to set the depthwrite shader.
*/
static INLINE void
-set_depth_fragment_shader(struct blit_state *ctx)
+set_depth_fragment_shader(struct blit_state *ctx,
+ enum pipe_texture_target pipe_tex)
{
- if (!ctx->fs_depth)
- ctx->fs_depth =
- util_make_fragment_tex_shader_writedepth(ctx->pipe, TGSI_TEXTURE_2D,
+ if (!ctx->fs_depth[pipe_tex]) {
+ unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex);
+
+ ctx->fs_depth[pipe_tex] =
+ util_make_fragment_tex_shader_writedepth(ctx->pipe, tgsi_tex,
TGSI_INTERPOLATE_LINEAR);
+ }
- cso_set_fragment_shader_handle(ctx->cso, ctx->fs_depth);
+ cso_set_fragment_shader_handle(ctx->cso, ctx->fs_depth[pipe_tex]);
}
{
const unsigned max_slots = 4096 / sizeof ctx->vertices;
- if (ctx->vbuf_slot >= max_slots)
- util_blit_flush( ctx );
+ if (ctx->vbuf_slot >= max_slots) {
+ pipe_resource_reference(&ctx->vbuf, NULL);
+ ctx->vbuf_slot = 0;
+ }
if (!ctx->vbuf) {
ctx->vbuf = pipe_buffer_create(ctx->pipe->screen,
}
+/**
+ * Can we blit from src format to dest format with a simple copy?
+ */
+static boolean
+formats_compatible(enum pipe_format src_format,
+ enum pipe_format dst_format)
+{
+ if (src_format == dst_format) {
+ return TRUE;
+ }
+ else {
+ const struct util_format_description *src_desc =
+ util_format_description(src_format);
+ const struct util_format_description *dst_desc =
+ util_format_description(dst_format);
+ return util_is_format_compatible(src_desc, dst_desc);
+ }
+}
+
+
/**
* Copy pixel block from src surface to dst surface.
* Overlapping regions are acceptable.
* XXX need some control over blitting stencil.
*/
void
-util_blit_pixels_writemask(struct blit_state *ctx,
- struct pipe_resource *src_tex,
- unsigned src_level,
- int srcX0, int srcY0,
- int srcX1, int srcY1,
- int srcZ0,
- struct pipe_surface *dst,
- int dstX0, int dstY0,
- int dstX1, int dstY1,
- float z, uint filter,
- uint writemask)
+util_blit_pixels(struct blit_state *ctx,
+ struct pipe_resource *src_tex,
+ unsigned src_level,
+ int srcX0, int srcY0,
+ int srcX1, int srcY1,
+ int srcZ0,
+ struct pipe_surface *dst,
+ int dstX0, int dstY0,
+ int dstX1, int dstY1,
+ float z, uint filter,
+ uint writemask)
{
struct pipe_context *pipe = ctx->pipe;
struct pipe_screen *screen = pipe->screen;
* no overlapping.
* Filter mode should not matter since there's no stretching.
*/
- if (dst_format == src_format &&
+ if (formats_compatible(src_format, dst_format) &&
srcX0 < srcX1 &&
dstX0 < dstX1 &&
srcY0 < srcY1 &&
dstX0, dstY0, dst->u.tex.first_layer,/* dest */
src_tex, src_level,
&src_box);
- return;
+ return;
}
if (dst_format == dst->format) {
dst_surface = pipe->create_surface(pipe, dst->texture, &templ);
}
- /* Create a temporary texture when src and dest alias or when src
- * is anything other than a 2d texture.
- * XXX should just use appropriate shader to access 1d / 3d slice / cube face,
- * much like the u_blitter code does (should be pretty trivial).
- *
- * This can still be improved upon.
+ /* Create a temporary texture when src and dest alias.
*/
- if ((src_tex == dst_surface->texture &&
+ if (src_tex == dst_surface->texture &&
dst_surface->u.tex.level == src_level &&
- dst_surface->u.tex.first_layer == srcZ0) ||
- (src_tex->target != PIPE_TEXTURE_2D &&
- src_tex->target != PIPE_TEXTURE_2D &&
- src_tex->target != PIPE_TEXTURE_RECT))
- {
+ dst_surface->u.tex.first_layer == srcZ0) {
+ /* Make a temporary texture which contains a copy of the source pixels.
+ * Then we'll sample from the temporary texture.
+ */
struct pipe_resource texTemp;
struct pipe_resource *tex;
struct pipe_sampler_view sv_templ;
pipe_resource_reference(&tex, NULL);
}
else {
+ /* Directly sample from the source resource/texture */
u_sampler_view_default_template(&sv_templ, src_tex, src_format);
sampler_view = pipe->create_sampler_view(pipe, src_tex, &sv_templ);
/* shaders */
if (dst_is_depth) {
- set_depth_fragment_shader(ctx);
+ set_depth_fragment_shader(ctx, sampler_view->texture->target);
} else {
- set_fragment_shader(ctx, writemask);
+ set_fragment_shader(ctx, writemask, sampler_view->texture->target);
}
set_vertex_shader(ctx);
cso_set_geometry_shader_handle(ctx->cso, NULL);
}
-void
-util_blit_pixels(struct blit_state *ctx,
- struct pipe_resource *src_tex,
- unsigned src_level,
- int srcX0, int srcY0,
- int srcX1, int srcY1,
- int srcZ,
- struct pipe_surface *dst,
- int dstX0, int dstY0,
- int dstX1, int dstY1,
- float z, uint filter )
-{
- util_blit_pixels_writemask( ctx, src_tex,
- src_level,
- srcX0, srcY0,
- srcX1, srcY1,
- srcZ,
- dst,
- dstX0, dstY0,
- dstX1, dstY1,
- z, filter,
- TGSI_WRITEMASK_XYZW );
-}
-
-
-/* Release vertex buffer at end of frame to avoid synchronous
- * rendering.
- */
-void util_blit_flush( struct blit_state *ctx )
-{
- pipe_resource_reference(&ctx->vbuf, NULL);
- ctx->vbuf_slot = 0;
-}
-
-
-
/**
* Copy pixel block from src texture to dst surface.
* The sampler view's first_level field indicates the source
cso_set_fragment_sampler_views(ctx->cso, 1, &src_sampler_view);
/* shaders */
- set_fragment_shader(ctx, TGSI_WRITEMASK_XYZW);
+ set_fragment_shader(ctx, TGSI_WRITEMASK_XYZW,
+ src_sampler_view->texture->target);
set_vertex_shader(ctx);
cso_set_geometry_shader_handle(ctx->cso, NULL);