diff options
Diffstat (limited to 'src/gallium/state_trackers/vega/renderer.c')
-rw-r--r-- | src/gallium/state_trackers/vega/renderer.c | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/src/gallium/state_trackers/vega/renderer.c b/src/gallium/state_trackers/vega/renderer.c index d326cfc5015..e14eb4706e4 100644 --- a/src/gallium/state_trackers/vega/renderer.c +++ b/src/gallium/state_trackers/vega/renderer.c @@ -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; }; @@ -321,6 +328,45 @@ static void renderer_set_samplers(struct renderer *r, } /** + * 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. */ static void renderer_quad_pos(struct renderer *r, @@ -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; |