/* Copy mipmap image between textures */ void st_texture_image_copy(struct pipe_context *pipe, struct pipe_texture *dst, GLuint dstLevel, struct pipe_texture *src, GLuint face) { struct pipe_screen *screen = pipe->screen; GLuint width = dst->width[dstLevel]; GLuint height = dst->height[dstLevel]; GLuint depth = dst->depth[dstLevel]; struct pipe_surface *src_surface; struct pipe_surface *dst_surface; GLuint i; for (i = 0; i < depth; i++) { GLuint srcLevel; /* find src texture level of needed size */ for (srcLevel = 0; srcLevel <= src->last_level; srcLevel++) { if (src->width[srcLevel] == width && src->height[srcLevel] == height) { break; } } assert(src->width[srcLevel] == width); assert(src->height[srcLevel] == height); #if 0 { src_surface = screen->get_tex_surface(screen, src, face, srcLevel, i, PIPE_BUFFER_USAGE_CPU_READ); ubyte *map = screen->surface_map(screen, src_surface, PIPE_BUFFER_USAGE_CPU_READ); map += src_surface->width * src_surface->height * 4 / 2; printf("%s center pixel: %d %d %d %d (pt %p[%d] -> %p[%d])\n", __FUNCTION__, map[0], map[1], map[2], map[3], src, srcLevel, dst, dstLevel); screen->surface_unmap(screen, src_surface); pipe_surface_reference(&src_surface, NULL); } #endif dst_surface = screen->get_tex_surface(screen, dst, face, dstLevel, i, PIPE_BUFFER_USAGE_GPU_WRITE); src_surface = screen->get_tex_surface(screen, src, face, srcLevel, i, PIPE_BUFFER_USAGE_GPU_READ); if (pipe->surface_copy) { pipe->surface_copy(pipe, dst_surface, 0, 0, /* destX, Y */ src_surface, 0, 0, /* srcX, Y */ width, height); } else { util_surface_copy(pipe, FALSE, dst_surface, 0, 0, /* destX, Y */ src_surface, 0, 0, /* srcX, Y */ width, height); } pipe_surface_reference(&src_surface, NULL); pipe_surface_reference(&dst_surface, NULL); } }
struct pipe_texture * renderer_clone_texture(struct xorg_renderer *r, struct pipe_texture *src) { enum pipe_format format; struct pipe_context *pipe = r->pipe; struct pipe_screen *screen = pipe->screen; struct pipe_texture *pt; struct pipe_texture templ; if (pipe->is_texture_referenced(pipe, src, 0, 0) & PIPE_REFERENCED_FOR_WRITE) pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); /* the coming in texture should already have that invariance */ debug_assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_SAMPLER, 0)); format = src->format; memset(&templ, 0, sizeof(templ)); templ.target = PIPE_TEXTURE_2D; templ.format = format; templ.last_level = 0; templ.width[0] = src->width[0]; templ.height[0] = src->height[0]; templ.depth[0] = 1; pf_get_block(format, &templ.block); templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER; pt = screen->texture_create(screen, &templ); debug_assert(!pt || pipe_is_referenced(&pt->reference)); if (!pt) return NULL; { /* copy source framebuffer surface into texture */ struct pipe_surface *ps_read = screen->get_tex_surface( screen, src, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ); struct pipe_surface *ps_tex = screen->get_tex_surface( screen, pt, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE ); if (pipe->surface_copy) { pipe->surface_copy(pipe, ps_tex, /* dest */ 0, 0, /* destx/y */ ps_read, 0, 0, src->width[0], src->height[0]); } else { util_surface_copy(pipe, FALSE, ps_tex, /* dest */ 0, 0, /* destx/y */ ps_read, 0, 0, src->width[0], src->height[0]); } pipe_surface_reference(&ps_read, NULL); pipe_surface_reference(&ps_tex, NULL); } return pt; }
void renderer_copy_surface(struct renderer *ctx, struct pipe_surface *src, int srcX0, int srcY0, int srcX1, int srcY1, struct pipe_surface *dst, int dstX0, int dstY0, int dstX1, int dstY1, float z, unsigned filter) { struct pipe_context *pipe = ctx->pipe; struct pipe_screen *screen = pipe->screen; struct pipe_buffer *buf; struct pipe_texture texTemp, *tex; struct pipe_surface *texSurf; struct pipe_framebuffer_state fb; struct st_framebuffer *stfb = ctx->owner->draw_buffer; const int srcW = abs(srcX1 - srcX0); const int srcH = abs(srcY1 - srcY0); const int srcLeft = MIN2(srcX0, srcX1); const int srcTop = MIN2(srcY0, srcY1); assert(filter == PIPE_TEX_MIPFILTER_NEAREST || filter == PIPE_TEX_MIPFILTER_LINEAR); if (srcLeft != srcX0) { /* left-right flip */ int tmp = dstX0; dstX0 = dstX1; dstX1 = tmp; } if (srcTop != srcY0) { /* up-down flip */ int tmp = dstY0; dstY0 = dstY1; dstY1 = tmp; } assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_SAMPLER, 0)); assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_SAMPLER, 0)); assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)); /* * XXX for now we're always creating a temporary texture. * Strictly speaking that's not always needed. */ /* create temp texture */ memset(&texTemp, 0, sizeof(texTemp)); texTemp.target = PIPE_TEXTURE_2D; texTemp.format = src->format; texTemp.last_level = 0; texTemp.width0 = srcW; texTemp.height0 = srcH; texTemp.depth0 = 1; tex = screen->texture_create(screen, &texTemp); if (!tex) return; texSurf = screen->get_tex_surface(screen, tex, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE); /* load temp texture */ if (pipe->surface_copy) { pipe->surface_copy(pipe, texSurf, 0, 0, /* dest */ src, srcLeft, srcTop, /* src */ srcW, srcH); /* size */ } else { util_surface_copy(pipe, FALSE, texSurf, 0, 0, /* dest */ src, srcLeft, srcTop, /* src */ srcW, srcH); /* size */ } /* free the surface, update the texture if necessary.*/ screen->tex_surface_destroy(texSurf); /* save state (restored below) */ cso_save_blend(ctx->cso); cso_save_samplers(ctx->cso); cso_save_sampler_textures(ctx->cso); cso_save_framebuffer(ctx->cso); cso_save_fragment_shader(ctx->cso); cso_save_vertex_shader(ctx->cso); cso_save_viewport(ctx->cso); /* set misc state we care about */ { struct pipe_blend_state blend; memset(&blend, 0, sizeof(blend)); blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; blend.rt[0].colormask = PIPE_MASK_RGBA; cso_set_blend(ctx->cso, &blend); } vg_set_viewport(ctx->owner, VEGA_Y0_TOP); /* sampler */ { struct pipe_sampler_state sampler; memset(&sampler, 0, sizeof(sampler)); sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; sampler.normalized_coords = 1; cso_single_sampler(ctx->cso, 0, &sampler); cso_single_sampler_done(ctx->cso); } /* texture */ cso_set_sampler_textures(ctx->cso, 1, &tex); /* shaders */ cso_set_fragment_shader_handle(ctx->cso, ctx->fs); cso_set_vertex_shader_handle(ctx->cso, vg_texture_vs(ctx->owner)); /* drawing dest */ if (stfb->strb->surface != dst) { memset(&fb, 0, sizeof(fb)); fb.width = dst->width; fb.height = dst->height; fb.nr_cbufs = 1; fb.cbufs[0] = dst; fb.zsbuf = stfb->dsrb->surface; cso_set_framebuffer(ctx->cso, &fb); } /* draw quad */ buf = setup_vertex_data(ctx, (float) dstX0, (float) dstY0, (float) dstX1, (float) dstY1, z); if (buf) { util_draw_vertex_buffer(ctx->pipe, buf, 0, PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ 2); /* attribs/vert */ pipe_buffer_reference( &buf, NULL ); } /* restore state we changed */ cso_restore_blend(ctx->cso); cso_restore_samplers(ctx->cso); cso_restore_sampler_textures(ctx->cso); cso_restore_framebuffer(ctx->cso); cso_restore_fragment_shader(ctx->cso); cso_restore_vertex_shader(ctx->cso); cso_restore_viewport(ctx->cso); pipe_texture_reference(&tex, NULL); }
static void setup_new_alpha_mask(struct vg_context *ctx, struct st_framebuffer *stfb, uint width, uint height) { struct pipe_context *pipe = ctx->pipe; struct pipe_texture *old_texture = stfb->alpha_mask; /* we use PIPE_FORMAT_A8R8G8B8_UNORM because we want to render to this texture and use it as a sampler, so while this wastes some space it makes both of those a lot simpler */ stfb->alpha_mask = create_texture(pipe, PIPE_FORMAT_A8R8G8B8_UNORM, width, height); if (!stfb->alpha_mask) { if (old_texture) pipe_texture_reference(&old_texture, NULL); return; } vg_validate_state(ctx); /* alpha mask starts with 1.f alpha */ mask_fill(0, 0, width, height, 1.f); /* if we had an old surface copy it over */ if (old_texture) { struct pipe_surface *surface = pipe->screen->get_tex_surface( pipe->screen, stfb->alpha_mask, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE); struct pipe_surface *old_surface = pipe->screen->get_tex_surface( pipe->screen, old_texture, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ); if (pipe->surface_copy) { pipe->surface_copy(pipe, surface, 0, 0, old_surface, 0, 0, MIN2(old_surface->width, width), MIN2(old_surface->height, height)); } else { util_surface_copy(pipe, FALSE, surface, 0, 0, old_surface, 0, 0, MIN2(old_surface->width, width), MIN2(old_surface->height, height)); } if (surface) pipe_surface_reference(&surface, NULL); if (old_surface) pipe_surface_reference(&old_surface, NULL); } /* Free the old texture */ if (old_texture) pipe_texture_reference(&old_texture, NULL); }