mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-06 11:38:05 +02:00
st/vega: Add FILTER renderer state for image filtering.
The state is designated to perform image filtering. execute_filter is updated to make use of the state.
This commit is contained in:
parent
6b241f532a
commit
e5968a5355
3 changed files with 225 additions and 174 deletions
|
|
@ -114,153 +114,11 @@ static INLINE struct pipe_sampler_view *create_texture_1d_view(struct vg_context
|
|||
return view;
|
||||
}
|
||||
|
||||
static INLINE struct pipe_surface * setup_framebuffer(struct vg_image *dst)
|
||||
{
|
||||
struct vg_context *ctx = vg_current_context();
|
||||
struct pipe_context *pipe = ctx->pipe;
|
||||
struct pipe_framebuffer_state fb;
|
||||
struct pipe_surface *dst_surf = pipe->screen->get_tex_surface(
|
||||
pipe->screen, dst->sampler_view->texture, 0, 0, 0,
|
||||
PIPE_BIND_RENDER_TARGET);
|
||||
|
||||
/* drawing dest */
|
||||
memset(&fb, 0, sizeof(fb));
|
||||
fb.width = dst->x + dst_surf->width;
|
||||
fb.height = dst->y + dst_surf->height;
|
||||
fb.nr_cbufs = 1;
|
||||
fb.cbufs[0] = dst_surf;
|
||||
{
|
||||
VGint i;
|
||||
for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i)
|
||||
fb.cbufs[i] = 0;
|
||||
}
|
||||
cso_set_framebuffer(ctx->cso_context, &fb);
|
||||
|
||||
return dst_surf;
|
||||
}
|
||||
|
||||
static void setup_viewport(struct vg_image *dst)
|
||||
{
|
||||
struct vg_context *ctx = vg_current_context();
|
||||
vg_set_viewport(ctx, VEGA_Y0_TOP);
|
||||
}
|
||||
|
||||
static void setup_blend()
|
||||
{
|
||||
struct vg_context *ctx = vg_current_context();
|
||||
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;
|
||||
if (ctx->state.vg.filter_channel_mask & VG_RED)
|
||||
blend.rt[0].colormask |= PIPE_MASK_R;
|
||||
if (ctx->state.vg.filter_channel_mask & VG_GREEN)
|
||||
blend.rt[0].colormask |= PIPE_MASK_G;
|
||||
if (ctx->state.vg.filter_channel_mask & VG_BLUE)
|
||||
blend.rt[0].colormask |= PIPE_MASK_B;
|
||||
if (ctx->state.vg.filter_channel_mask & VG_ALPHA)
|
||||
blend.rt[0].colormask |= PIPE_MASK_A;
|
||||
blend.rt[0].blend_enable = 0;
|
||||
cso_set_blend(ctx->cso_context, &blend);
|
||||
}
|
||||
|
||||
static void setup_constant_buffer(struct vg_context *ctx, const void *buffer,
|
||||
VGint param_bytes)
|
||||
{
|
||||
struct pipe_context *pipe = ctx->pipe;
|
||||
struct pipe_resource **cbuf = &ctx->filter.buffer;
|
||||
|
||||
/* We always need to get a new buffer, to keep the drivers simple and
|
||||
* avoid gratuitous rendering synchronization. */
|
||||
pipe_resource_reference(cbuf, NULL);
|
||||
|
||||
*cbuf = pipe_buffer_create(pipe->screen,
|
||||
PIPE_BIND_CONSTANT_BUFFER,
|
||||
param_bytes);
|
||||
|
||||
if (*cbuf) {
|
||||
st_no_flush_pipe_buffer_write(ctx, *cbuf,
|
||||
0, param_bytes, buffer);
|
||||
}
|
||||
|
||||
ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, *cbuf);
|
||||
}
|
||||
|
||||
static void setup_samplers(struct vg_context *ctx, struct filter_info *info)
|
||||
{
|
||||
struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
|
||||
struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
|
||||
struct pipe_sampler_state sampler[3];
|
||||
int num_samplers = 0;
|
||||
int num_textures = 0;
|
||||
|
||||
samplers[0] = NULL;
|
||||
samplers[1] = NULL;
|
||||
samplers[2] = NULL;
|
||||
samplers[3] = NULL;
|
||||
sampler_views[0] = NULL;
|
||||
sampler_views[1] = NULL;
|
||||
sampler_views[2] = NULL;
|
||||
sampler_views[3] = NULL;
|
||||
|
||||
memset(&sampler[0], 0, sizeof(struct pipe_sampler_state));
|
||||
sampler[0].wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
|
||||
sampler[0].wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
|
||||
sampler[0].wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
|
||||
sampler[0].min_img_filter = PIPE_TEX_MIPFILTER_LINEAR;
|
||||
sampler[0].mag_img_filter = PIPE_TEX_MIPFILTER_LINEAR;
|
||||
sampler[0].normalized_coords = 1;
|
||||
|
||||
switch(info->tiling_mode) {
|
||||
case VG_TILE_FILL:
|
||||
sampler[0].wrap_s = PIPE_TEX_WRAP_CLAMP_TO_BORDER;
|
||||
sampler[0].wrap_t = PIPE_TEX_WRAP_CLAMP_TO_BORDER;
|
||||
memcpy(sampler[0].border_color,
|
||||
ctx->state.vg.tile_fill_color,
|
||||
sizeof(VGfloat) * 4);
|
||||
break;
|
||||
case VG_TILE_PAD:
|
||||
sampler[0].wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
|
||||
sampler[0].wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
|
||||
break;
|
||||
case VG_TILE_REPEAT:
|
||||
sampler[0].wrap_s = PIPE_TEX_WRAP_REPEAT;
|
||||
sampler[0].wrap_t = PIPE_TEX_WRAP_REPEAT;
|
||||
break;
|
||||
case VG_TILE_REFLECT:
|
||||
sampler[0].wrap_s = PIPE_TEX_WRAP_MIRROR_REPEAT;
|
||||
sampler[0].wrap_t = PIPE_TEX_WRAP_MIRROR_REPEAT;
|
||||
break;
|
||||
default:
|
||||
debug_assert(!"Unknown tiling mode");
|
||||
}
|
||||
|
||||
samplers[0] = &sampler[0];
|
||||
sampler_views[0] = info->src->sampler_view;
|
||||
++num_samplers;
|
||||
++num_textures;
|
||||
|
||||
if (info->extra_texture_view) {
|
||||
memcpy(&sampler[1], &sampler[0], sizeof(struct pipe_sampler_state));
|
||||
samplers[1] = &sampler[1];
|
||||
sampler_views[1] = info->extra_texture_view;
|
||||
++num_samplers;
|
||||
++num_textures;
|
||||
}
|
||||
|
||||
|
||||
cso_set_samplers(ctx->cso_context, num_samplers, (const struct pipe_sampler_state **)samplers);
|
||||
cso_set_fragment_sampler_views(ctx->cso_context, num_textures, sampler_views);
|
||||
}
|
||||
|
||||
static struct vg_shader * setup_color_matrix(struct vg_context *ctx, void *user_data)
|
||||
{
|
||||
struct vg_shader *shader =
|
||||
shader_create_from_text(ctx->pipe, color_matrix_asm, 200,
|
||||
PIPE_SHADER_FRAGMENT);
|
||||
cso_set_fragment_shader_handle(ctx->cso_context, shader->driver);
|
||||
return shader;
|
||||
}
|
||||
|
||||
|
|
@ -275,7 +133,6 @@ static struct vg_shader * setup_convolution(struct vg_context *ctx, void *user_d
|
|||
shader = shader_create_from_text(ctx->pipe, buffer, 200,
|
||||
PIPE_SHADER_FRAGMENT);
|
||||
|
||||
cso_set_fragment_shader_handle(ctx->cso_context, shader->driver);
|
||||
return shader;
|
||||
}
|
||||
|
||||
|
|
@ -285,7 +142,6 @@ static struct vg_shader * setup_lookup(struct vg_context *ctx, void *user_data)
|
|||
shader_create_from_text(ctx->pipe, lookup_asm,
|
||||
200, PIPE_SHADER_FRAGMENT);
|
||||
|
||||
cso_set_fragment_shader_handle(ctx->cso_context, shader->driver);
|
||||
return shader;
|
||||
}
|
||||
|
||||
|
|
@ -316,49 +172,67 @@ static struct vg_shader * setup_lookup_single(struct vg_context *ctx, void *user
|
|||
shader = shader_create_from_text(ctx->pipe, buffer, 200,
|
||||
PIPE_SHADER_FRAGMENT);
|
||||
|
||||
cso_set_fragment_shader_handle(ctx->cso_context, shader->driver);
|
||||
return shader;
|
||||
}
|
||||
|
||||
static void execute_filter(struct vg_context *ctx,
|
||||
struct filter_info *info)
|
||||
{
|
||||
struct pipe_surface *dst_surf;
|
||||
struct vg_shader *shader;
|
||||
const struct pipe_sampler_state *samplers[2];
|
||||
struct pipe_sampler_view *views[2];
|
||||
struct pipe_sampler_state sampler;
|
||||
uint tex_wrap;
|
||||
|
||||
cso_save_framebuffer(ctx->cso_context);
|
||||
cso_save_fragment_shader(ctx->cso_context);
|
||||
cso_save_viewport(ctx->cso_context);
|
||||
cso_save_blend(ctx->cso_context);
|
||||
cso_save_samplers(ctx->cso_context);
|
||||
cso_save_fragment_sampler_views(ctx->cso_context);
|
||||
memset(&sampler, 0, sizeof(sampler));
|
||||
sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR;
|
||||
sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
|
||||
sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
|
||||
sampler.normalized_coords = 1;
|
||||
|
||||
switch (info->tiling_mode) {
|
||||
case VG_TILE_FILL:
|
||||
tex_wrap = PIPE_TEX_WRAP_CLAMP_TO_BORDER;
|
||||
/* copy border color */
|
||||
memcpy(sampler.border_color, ctx->state.vg.tile_fill_color,
|
||||
sizeof(sampler.border_color));
|
||||
break;
|
||||
case VG_TILE_PAD:
|
||||
tex_wrap = PIPE_TEX_WRAP_CLAMP_TO_EDGE;;
|
||||
break;
|
||||
case VG_TILE_REPEAT:
|
||||
tex_wrap = PIPE_TEX_WRAP_REPEAT;;
|
||||
break;
|
||||
case VG_TILE_REFLECT:
|
||||
tex_wrap = PIPE_TEX_WRAP_MIRROR_REPEAT;
|
||||
break;
|
||||
default:
|
||||
debug_assert(!"Unknown tiling mode");
|
||||
break;
|
||||
}
|
||||
|
||||
sampler.wrap_s = tex_wrap;
|
||||
sampler.wrap_t = tex_wrap;
|
||||
sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
|
||||
|
||||
samplers[0] = samplers[1] = &sampler;
|
||||
views[0] = info->src->sampler_view;
|
||||
views[1] = info->extra_texture_view;
|
||||
|
||||
dst_surf = setup_framebuffer(info->dst);
|
||||
setup_viewport(info->dst);
|
||||
setup_blend();
|
||||
setup_constant_buffer(ctx, info->const_buffer, info->const_buffer_len);
|
||||
shader = info->setup_shader(ctx, info->user_data);
|
||||
setup_samplers(ctx, info);
|
||||
|
||||
renderer_draw_texture(ctx->renderer,
|
||||
info->src->sampler_view->texture,
|
||||
info->dst->x, info->dst->y,
|
||||
info->dst->x + info->dst->width,
|
||||
info->dst->y + info->dst->height,
|
||||
info->dst->x, info->dst->y,
|
||||
info->dst->x + info->dst->width,
|
||||
info->dst->y + info->dst->height);
|
||||
|
||||
cso_restore_framebuffer(ctx->cso_context);
|
||||
cso_restore_fragment_shader(ctx->cso_context);
|
||||
cso_restore_viewport(ctx->cso_context);
|
||||
cso_restore_blend(ctx->cso_context);
|
||||
cso_restore_samplers(ctx->cso_context);
|
||||
cso_restore_fragment_sampler_views(ctx->cso_context);
|
||||
if (renderer_filter_begin(ctx->renderer,
|
||||
info->dst->sampler_view->texture, VG_TRUE,
|
||||
ctx->state.vg.filter_channel_mask,
|
||||
samplers, views, (info->extra_texture_view) ? 2 : 1,
|
||||
shader->driver, info->const_buffer, info->const_buffer_len)) {
|
||||
renderer_filter(ctx->renderer,
|
||||
info->dst->x, info->dst->y, info->dst->width, info->dst->height,
|
||||
info->src->x, info->src->y, info->src->width, info->src->height);
|
||||
renderer_filter_end(ctx->renderer);
|
||||
}
|
||||
|
||||
vg_shader_destroy(ctx, shader);
|
||||
|
||||
pipe_surface_reference(&dst_surf, NULL);
|
||||
}
|
||||
|
||||
void vegaColorMatrix(VGImage dst, VGImage src,
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "renderer.h"
|
||||
|
||||
#include "vg_context.h"
|
||||
#include "image.h"
|
||||
|
||||
#include "pipe/p_context.h"
|
||||
#include "pipe/p_state.h"
|
||||
|
|
@ -49,6 +50,7 @@ typedef enum {
|
|||
RENDERER_STATE_DRAWTEX,
|
||||
RENDERER_STATE_SCISSOR,
|
||||
RENDERER_STATE_CLEAR,
|
||||
RENDERER_STATE_FILTER,
|
||||
NUM_RENDERER_STATES
|
||||
} RendererState;
|
||||
|
||||
|
|
@ -96,6 +98,11 @@ struct renderer {
|
|||
struct {
|
||||
VGboolean restore_dsa;
|
||||
} scissor;
|
||||
|
||||
struct {
|
||||
VGboolean use_sampler;
|
||||
VGint tex_width, tex_height;
|
||||
} filter;
|
||||
} u;
|
||||
};
|
||||
|
||||
|
|
@ -320,6 +327,45 @@ static void renderer_set_samplers(struct renderer *r,
|
|||
cso_set_fragment_sampler_views(r->cso, num_views, views);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set custom renderer fragment shader, and optionally set samplers and views
|
||||
* and upload the fragment constant buffer.
|
||||
*
|
||||
* This function modifies fragment_shader, samplers and fragment_sampler_views
|
||||
* states.
|
||||
*/
|
||||
static void renderer_set_custom_fs(struct renderer *renderer,
|
||||
void *fs,
|
||||
const struct pipe_sampler_state **samplers,
|
||||
struct pipe_sampler_view **views,
|
||||
VGint num_samplers,
|
||||
const void *const_buffer,
|
||||
VGint const_buffer_len)
|
||||
{
|
||||
cso_set_fragment_shader_handle(renderer->cso, fs);
|
||||
|
||||
/* set samplers and views */
|
||||
if (num_samplers) {
|
||||
cso_set_samplers(renderer->cso, num_samplers, samplers);
|
||||
cso_set_fragment_sampler_views(renderer->cso, num_samplers, views);
|
||||
}
|
||||
|
||||
/* upload fs constant buffer */
|
||||
if (const_buffer_len) {
|
||||
struct pipe_resource *cbuf;
|
||||
|
||||
cbuf = pipe_buffer_create(renderer->pipe->screen,
|
||||
PIPE_BIND_CONSTANT_BUFFER, const_buffer_len);
|
||||
pipe_buffer_write(renderer->pipe, cbuf, 0,
|
||||
const_buffer_len, const_buffer);
|
||||
renderer->pipe->set_constant_buffer(renderer->pipe,
|
||||
PIPE_SHADER_FRAGMENT, 0, cbuf);
|
||||
|
||||
/* destroy cbuf automatically */
|
||||
pipe_resource_reference(&cbuf, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup renderer quad position.
|
||||
*/
|
||||
|
|
@ -678,6 +724,119 @@ void renderer_clear_end(struct renderer *renderer)
|
|||
renderer->state = RENDERER_STATE_INIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the renderer for image filtering.
|
||||
*/
|
||||
VGboolean renderer_filter_begin(struct renderer *renderer,
|
||||
struct pipe_resource *dst,
|
||||
VGboolean y0_top,
|
||||
VGbitfield channel_mask,
|
||||
const struct pipe_sampler_state **samplers,
|
||||
struct pipe_sampler_view **views,
|
||||
VGint num_samplers,
|
||||
void *fs,
|
||||
const void *const_buffer,
|
||||
VGint const_buffer_len)
|
||||
{
|
||||
struct pipe_surface *surf;
|
||||
|
||||
assert(renderer->state == RENDERER_STATE_INIT);
|
||||
|
||||
if (!fs)
|
||||
return VG_FALSE;
|
||||
if (!renderer_can_support(renderer, dst, PIPE_BIND_RENDER_TARGET))
|
||||
return VG_FALSE;
|
||||
|
||||
surf = renderer->pipe->screen->get_tex_surface(renderer->pipe->screen,
|
||||
dst, 0, 0, 0, PIPE_BIND_RENDER_TARGET);
|
||||
if (!surf)
|
||||
return VG_FALSE;
|
||||
|
||||
cso_save_framebuffer(renderer->cso);
|
||||
cso_save_viewport(renderer->cso);
|
||||
cso_save_blend(renderer->cso);
|
||||
|
||||
/* set the image as the target */
|
||||
renderer_set_target(renderer, surf, NULL, y0_top);
|
||||
pipe_surface_reference(&surf, NULL);
|
||||
|
||||
renderer_set_blend(renderer, channel_mask);
|
||||
|
||||
if (num_samplers) {
|
||||
struct pipe_resource *tex;
|
||||
|
||||
cso_save_samplers(renderer->cso);
|
||||
cso_save_fragment_sampler_views(renderer->cso);
|
||||
cso_save_fragment_shader(renderer->cso);
|
||||
cso_save_vertex_shader(renderer->cso);
|
||||
|
||||
renderer_set_custom_fs(renderer, fs,
|
||||
samplers, views, num_samplers,
|
||||
const_buffer, const_buffer_len);
|
||||
renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
|
||||
|
||||
tex = views[0]->texture;
|
||||
renderer->u.filter.tex_width = tex->width0;
|
||||
renderer->u.filter.tex_height = tex->height0;
|
||||
renderer->u.filter.use_sampler = VG_TRUE;
|
||||
}
|
||||
else {
|
||||
cso_save_fragment_shader(renderer->cso);
|
||||
|
||||
renderer_set_custom_fs(renderer, fs, NULL, NULL, 0,
|
||||
const_buffer, const_buffer_len);
|
||||
|
||||
renderer->u.filter.use_sampler = VG_FALSE;
|
||||
}
|
||||
|
||||
renderer->state = RENDERER_STATE_FILTER;
|
||||
|
||||
return VG_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw into a rectangle of the destination with the specified region of the
|
||||
* texture(s).
|
||||
*
|
||||
* The coordinates are in surface coordinates.
|
||||
*/
|
||||
void renderer_filter(struct renderer *renderer,
|
||||
VGint x, VGint y, VGint w, VGint h,
|
||||
VGint sx, VGint sy, VGint sw, VGint sh)
|
||||
{
|
||||
assert(renderer->state == RENDERER_STATE_FILTER);
|
||||
|
||||
renderer_quad_pos(renderer, x, y, x + w, y + h, VG_FALSE);
|
||||
if (renderer->u.filter.use_sampler) {
|
||||
renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
|
||||
renderer->u.filter.tex_width,
|
||||
renderer->u.filter.tex_height);
|
||||
}
|
||||
|
||||
renderer_quad_draw(renderer);
|
||||
}
|
||||
|
||||
/**
|
||||
* End image filtering and restore the states.
|
||||
*/
|
||||
void renderer_filter_end(struct renderer *renderer)
|
||||
{
|
||||
assert(renderer->state == RENDERER_STATE_FILTER);
|
||||
|
||||
if (renderer->u.filter.use_sampler) {
|
||||
cso_restore_samplers(renderer->cso);
|
||||
cso_restore_fragment_sampler_views(renderer->cso);
|
||||
cso_restore_vertex_shader(renderer->cso);
|
||||
}
|
||||
|
||||
cso_restore_framebuffer(renderer->cso);
|
||||
cso_restore_viewport(renderer->cso);
|
||||
cso_restore_blend(renderer->cso);
|
||||
cso_restore_fragment_shader(renderer->cso);
|
||||
|
||||
renderer->state = RENDERER_STATE_INIT;
|
||||
}
|
||||
|
||||
static void setup_shaders(struct renderer *ctx)
|
||||
{
|
||||
struct pipe_context *pipe = ctx->pipe;
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ struct renderer;
|
|||
|
||||
struct vg_context;
|
||||
struct pipe_resource;
|
||||
struct pipe_sampler_state;
|
||||
struct pipe_sampler_view;
|
||||
struct pipe_surface;
|
||||
|
||||
|
|
@ -76,6 +77,23 @@ void renderer_clear(struct renderer *renderer,
|
|||
|
||||
void renderer_clear_end(struct renderer *renderer);
|
||||
|
||||
VGboolean renderer_filter_begin(struct renderer *renderer,
|
||||
struct pipe_resource *dst,
|
||||
VGboolean y0_top,
|
||||
VGbitfield channel_mask,
|
||||
const struct pipe_sampler_state **samplers,
|
||||
struct pipe_sampler_view **views,
|
||||
VGint num_samplers,
|
||||
void *fs,
|
||||
const void *const_buffer,
|
||||
VGint const_buffer_len);
|
||||
|
||||
void renderer_filter(struct renderer *renderer,
|
||||
VGint x, VGint y, VGint w, VGint h,
|
||||
VGint sx, VGint sy, VGint sw, VGint sh);
|
||||
|
||||
void renderer_filter_end(struct renderer *renderer);
|
||||
|
||||
void renderer_draw_quad(struct renderer *,
|
||||
VGfloat x1, VGfloat y1,
|
||||
VGfloat x2, VGfloat y2,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue