diff options
Diffstat (limited to 'src/gallium/state_trackers/vega/renderer.c')
-rw-r--r-- | src/gallium/state_trackers/vega/renderer.c | 1558 |
1 files changed, 0 insertions, 1558 deletions
diff --git a/src/gallium/state_trackers/vega/renderer.c b/src/gallium/state_trackers/vega/renderer.c deleted file mode 100644 index d369c323bcc..00000000000 --- a/src/gallium/state_trackers/vega/renderer.c +++ /dev/null @@ -1,1558 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. All Rights Reserved. - * Copyright 2010 LunarG, Inc. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "renderer.h" - -#include "vg_context.h" - -#include "pipe/p_context.h" -#include "pipe/p_state.h" -#include "util/u_inlines.h" -#include "pipe/p_screen.h" -#include "pipe/p_shader_tokens.h" - -#include "util/u_draw_quad.h" -#include "util/u_simple_shaders.h" -#include "util/u_memory.h" -#include "util/u_sampler.h" -#include "util/u_surface.h" -#include "util/u_math.h" -#include "util/u_format.h" - -#include "cso_cache/cso_context.h" -#include "tgsi/tgsi_ureg.h" - -typedef enum { - RENDERER_STATE_INIT, - RENDERER_STATE_COPY, - RENDERER_STATE_DRAWTEX, - RENDERER_STATE_SCISSOR, - RENDERER_STATE_CLEAR, - RENDERER_STATE_FILTER, - RENDERER_STATE_POLYGON_STENCIL, - RENDERER_STATE_POLYGON_FILL, - NUM_RENDERER_STATES -} RendererState; - -typedef enum { - RENDERER_VS_PLAIN, - RENDERER_VS_COLOR, - RENDERER_VS_TEXTURE, - NUM_RENDERER_VS -} RendererVs; - -typedef enum { - RENDERER_FS_COLOR, - RENDERER_FS_TEXTURE, - RENDERER_FS_SCISSOR, - RENDERER_FS_WHITE, - NUM_RENDERER_FS -} RendererFs; - -struct renderer { - struct pipe_context *pipe; - struct cso_context *cso; - - VGbitfield dirty; - struct { - struct pipe_rasterizer_state rasterizer; - struct pipe_depth_stencil_alpha_state dsa; - struct pipe_framebuffer_state fb; - } g3d; - struct matrix projection; - - struct matrix mvp; - struct pipe_resource *vs_cbuf; - - struct pipe_resource *fs_cbuf; - VGfloat fs_cbuf_data[32]; - VGint fs_cbuf_len; - - struct pipe_vertex_element velems[2]; - VGfloat vertices[4][2][4]; - - void *cached_vs[NUM_RENDERER_VS]; - void *cached_fs[NUM_RENDERER_FS]; - - RendererState state; - - /* state data */ - union { - struct { - VGint tex_width; - VGint tex_height; - } copy; - - struct { - VGint tex_width; - VGint tex_height; - } drawtex; - - struct { - VGboolean restore_dsa; - } scissor; - - struct { - VGboolean use_sampler; - VGint tex_width, tex_height; - } filter; - - struct { - struct pipe_depth_stencil_alpha_state dsa; - VGboolean manual_two_sides; - VGboolean restore_dsa; - } polygon_stencil; - } u; -}; - -/** - * Return VG_TRUE if the renderer can use the resource as the asked bindings. - */ -static VGboolean renderer_can_support(struct renderer *renderer, - struct pipe_resource *res, - unsigned bindings) -{ - struct pipe_screen *screen = renderer->pipe->screen; - - return screen->is_format_supported(screen, - res->format, res->target, 0, bindings); -} - -/** - * Set the model-view-projection matrix used by vertex shaders. - */ -static void renderer_set_mvp(struct renderer *renderer, - const struct matrix *mvp) -{ - struct matrix *cur = &renderer->mvp; - struct pipe_resource *cbuf; - VGfloat consts[3][4]; - VGint i; - - /* projection only */ - if (!mvp) - mvp = &renderer->projection; - - /* re-upload only if necessary */ - if (memcmp(cur, mvp, sizeof(*mvp)) == 0) - return; - - /* 3x3 matrix to 3 constant vectors (no Z) */ - for (i = 0; i < 3; i++) { - consts[i][0] = mvp->m[i + 0]; - consts[i][1] = mvp->m[i + 3]; - consts[i][2] = 0.0f; - consts[i][3] = mvp->m[i + 6]; - } - - cbuf = renderer->vs_cbuf; - pipe_resource_reference(&cbuf, NULL); - cbuf = pipe_buffer_create(renderer->pipe->screen, - PIPE_BIND_CONSTANT_BUFFER, - PIPE_USAGE_DEFAULT, - sizeof(consts)); - if (cbuf) { - pipe_buffer_write(renderer->pipe, cbuf, - 0, sizeof(consts), consts); - } - pipe_set_constant_buffer(renderer->pipe, - PIPE_SHADER_VERTEX, 0, cbuf); - - memcpy(cur, mvp, sizeof(*mvp)); - renderer->vs_cbuf = cbuf; -} - -/** - * Create a simple vertex shader that passes through position and the given - * attribute. - */ -static void *create_passthrough_vs(struct pipe_context *pipe, int semantic_name) -{ - struct ureg_program *ureg; - struct ureg_src src[2], constants[3]; - struct ureg_dst dst[2], tmp; - int i; - - ureg = ureg_create(TGSI_PROCESSOR_VERTEX); - if (!ureg) - return NULL; - - /* position is in user coordinates */ - src[0] = ureg_DECL_vs_input(ureg, 0); - dst[0] = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); - tmp = ureg_DECL_temporary(ureg); - for (i = 0; i < Elements(constants); i++) - constants[i] = ureg_DECL_constant(ureg, i); - - /* transform to clipped coordinates */ - ureg_DP4(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), src[0], constants[0]); - ureg_DP4(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Y), src[0], constants[1]); - ureg_MOV(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Z), src[0]); - ureg_DP4(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_W), src[0], constants[2]); - ureg_MOV(ureg, dst[0], ureg_src(tmp)); - - if (semantic_name >= 0) { - src[1] = ureg_DECL_vs_input(ureg, 1); - dst[1] = ureg_DECL_output(ureg, semantic_name, 0); - ureg_MOV(ureg, dst[1], src[1]); - } - - ureg_END(ureg); - - return ureg_create_shader_and_destroy(ureg, pipe); -} - -/** - * Set renderer vertex shader. - * - * This function modifies vertex_shader state. - */ -static void renderer_set_vs(struct renderer *r, RendererVs id) -{ - /* create as needed */ - if (!r->cached_vs[id]) { - int semantic_name = -1; - - switch (id) { - case RENDERER_VS_PLAIN: - break; - case RENDERER_VS_COLOR: - semantic_name = TGSI_SEMANTIC_COLOR; - break; - case RENDERER_VS_TEXTURE: - semantic_name = TGSI_SEMANTIC_GENERIC; - break; - default: - assert(!"Unknown renderer vs id"); - break; - } - - r->cached_vs[id] = create_passthrough_vs(r->pipe, semantic_name); - } - - cso_set_vertex_shader_handle(r->cso, r->cached_vs[id]); -} - -/** - * Create a simple fragment shader that sets the depth to 0.0f. - */ -static void *create_scissor_fs(struct pipe_context *pipe) -{ - struct ureg_program *ureg; - struct ureg_dst out; - struct ureg_src imm; - - ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT); - out = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); - imm = ureg_imm4f(ureg, 0.0f, 0.0f, 0.0f, 0.0f); - - ureg_MOV(ureg, ureg_writemask(out, TGSI_WRITEMASK_Z), imm); - ureg_END(ureg); - - return ureg_create_shader_and_destroy(ureg, pipe); -} - -/** - * Create a simple fragment shader that sets the color to white. - */ -static void *create_white_fs(struct pipe_context *pipe) -{ - struct ureg_program *ureg; - struct ureg_dst out; - struct ureg_src imm; - - ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT); - out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); - imm = ureg_imm4f(ureg, 1.0f, 1.0f, 1.0f, 1.0f); - - ureg_MOV(ureg, out, imm); - ureg_END(ureg); - - return ureg_create_shader_and_destroy(ureg, pipe); -} - -/** - * Set renderer fragment shader. - * - * This function modifies fragment_shader state. - */ -static void renderer_set_fs(struct renderer *r, RendererFs id) -{ - /* create as needed */ - if (!r->cached_fs[id]) { - void *fs = NULL; - - switch (id) { - case RENDERER_FS_COLOR: - fs = util_make_fragment_passthrough_shader(r->pipe, - TGSI_SEMANTIC_COLOR, TGSI_INTERPOLATE_PERSPECTIVE, - TRUE); - break; - case RENDERER_FS_TEXTURE: - fs = util_make_fragment_tex_shader(r->pipe, - TGSI_TEXTURE_2D, TGSI_INTERPOLATE_LINEAR); - break; - case RENDERER_FS_SCISSOR: - fs = create_scissor_fs(r->pipe); - break; - case RENDERER_FS_WHITE: - fs = create_white_fs(r->pipe); - break; - default: - assert(!"Unknown renderer fs id"); - break; - } - - r->cached_fs[id] = fs; - } - - cso_set_fragment_shader_handle(r->cso, r->cached_fs[id]); -} - -typedef enum { - VEGA_Y0_TOP, - VEGA_Y0_BOTTOM -} VegaOrientation; - -static void vg_set_viewport(struct renderer *r, - VegaOrientation orientation) -{ - const struct pipe_framebuffer_state *fb = &r->g3d.fb; - struct pipe_viewport_state viewport; - VGfloat y_scale = (orientation == VEGA_Y0_BOTTOM) ? -2.f : 2.f; - - viewport.scale[0] = fb->width / 2.f; - viewport.scale[1] = fb->height / y_scale; - viewport.scale[2] = 1.0; - viewport.translate[0] = fb->width / 2.f; - viewport.translate[1] = fb->height / 2.f; - viewport.translate[2] = 0.0; - - cso_set_viewport(r->cso, &viewport); -} - -/** - * Set renderer target. - * - * This function modifies framebuffer and viewport states. - */ -static void renderer_set_target(struct renderer *r, - struct pipe_surface *cbuf, - struct pipe_surface *zsbuf, - VGboolean y0_top) -{ - struct pipe_framebuffer_state fb; - - memset(&fb, 0, sizeof(fb)); - fb.width = cbuf->width; - fb.height = cbuf->height; - fb.cbufs[0] = cbuf; - fb.nr_cbufs = 1; - fb.zsbuf = zsbuf; - cso_set_framebuffer(r->cso, &fb); - - vg_set_viewport(r, (y0_top) ? VEGA_Y0_TOP : VEGA_Y0_BOTTOM); -} - -/** - * Set renderer blend state. Blending is disabled. - * - * This function modifies blend state. - */ -static void renderer_set_blend(struct renderer *r, - VGbitfield channel_mask) -{ - 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 (channel_mask & VG_RED) - blend.rt[0].colormask |= PIPE_MASK_R; - if (channel_mask & VG_GREEN) - blend.rt[0].colormask |= PIPE_MASK_G; - if (channel_mask & VG_BLUE) - blend.rt[0].colormask |= PIPE_MASK_B; - if (channel_mask & VG_ALPHA) - blend.rt[0].colormask |= PIPE_MASK_A; - - cso_set_blend(r->cso, &blend); -} - -/** - * Set renderer sampler and view states. - * - * This function modifies samplers and fragment_sampler_views states. - */ -static void renderer_set_samplers(struct renderer *r, - uint num_views, - struct pipe_sampler_view **views) -{ - struct pipe_sampler_state sampler; - unsigned tex_filter = PIPE_TEX_FILTER_NEAREST; - unsigned tex_wrap = PIPE_TEX_WRAP_CLAMP_TO_EDGE; - uint i; - - memset(&sampler, 0, sizeof(sampler)); - - sampler.min_img_filter = tex_filter; - sampler.mag_img_filter = tex_filter; - sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; - - sampler.wrap_s = tex_wrap; - sampler.wrap_t = tex_wrap; - sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; - - sampler.normalized_coords = 1; - - /* set samplers */ - for (i = 0; i < num_views; i++) - cso_single_sampler(r->cso, PIPE_SHADER_FRAGMENT, i, &sampler); - cso_single_sampler_done(r->cso, PIPE_SHADER_FRAGMENT); - - /* set views */ - cso_set_sampler_views(r->cso, PIPE_SHADER_FRAGMENT, 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, PIPE_SHADER_FRAGMENT, num_samplers, samplers); - cso_set_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT, num_samplers, views); - } - - /* upload fs constant buffer */ - if (const_buffer_len) { - struct pipe_resource *cbuf = renderer->fs_cbuf; - - if (!cbuf || renderer->fs_cbuf_len != const_buffer_len || - memcmp(renderer->fs_cbuf_data, const_buffer, const_buffer_len)) { - pipe_resource_reference(&cbuf, NULL); - - cbuf = pipe_buffer_create(renderer->pipe->screen, - PIPE_BIND_CONSTANT_BUFFER, PIPE_USAGE_DEFAULT, - const_buffer_len); - pipe_buffer_write(renderer->pipe, cbuf, 0, - const_buffer_len, const_buffer); - pipe_set_constant_buffer(renderer->pipe, - PIPE_SHADER_FRAGMENT, 0, cbuf); - - renderer->fs_cbuf = cbuf; - if (const_buffer_len <= sizeof(renderer->fs_cbuf_data)) { - memcpy(renderer->fs_cbuf_data, const_buffer, const_buffer_len); - renderer->fs_cbuf_len = const_buffer_len; - } - else { - renderer->fs_cbuf_len = 0; - } - } - } -} - -/** - * Setup renderer quad position. - */ -static void renderer_quad_pos(struct renderer *r, - VGfloat x0, VGfloat y0, - VGfloat x1, VGfloat y1, - VGboolean scissor) -{ - VGfloat z; - - /* the depth test is used for scissoring */ - z = (scissor) ? 0.0f : 1.0f; - - /* positions */ - r->vertices[0][0][0] = x0; - r->vertices[0][0][1] = y0; - r->vertices[0][0][2] = z; - - r->vertices[1][0][0] = x1; - r->vertices[1][0][1] = y0; - r->vertices[1][0][2] = z; - - r->vertices[2][0][0] = x1; - r->vertices[2][0][1] = y1; - r->vertices[2][0][2] = z; - - r->vertices[3][0][0] = x0; - r->vertices[3][0][1] = y1; - r->vertices[3][0][2] = z; -} - -/** - * Setup renderer quad texture coordinates. - */ -static void renderer_quad_texcoord(struct renderer *r, - VGfloat x0, VGfloat y0, - VGfloat x1, VGfloat y1, - VGint tex_width, VGint tex_height) -{ - VGfloat s0, t0, s1, t1, r0, q0; - VGint i; - - s0 = x0 / tex_width; - s1 = x1 / tex_width; - t0 = y0 / tex_height; - t1 = y1 / tex_height; - r0 = 0.0f; - q0 = 1.0f; - - /* texcoords */ - r->vertices[0][1][0] = s0; - r->vertices[0][1][1] = t0; - - r->vertices[1][1][0] = s1; - r->vertices[1][1][1] = t0; - - r->vertices[2][1][0] = s1; - r->vertices[2][1][1] = t1; - - r->vertices[3][1][0] = s0; - r->vertices[3][1][1] = t1; - - for (i = 0; i < 4; i++) { - r->vertices[i][1][2] = r0; - r->vertices[i][1][3] = q0; - } -} - -/** - * Draw renderer quad. - */ -static void renderer_quad_draw(struct renderer *r) -{ - util_draw_user_vertex_buffer(r->cso, r->vertices, PIPE_PRIM_TRIANGLE_FAN, - Elements(r->vertices), /* verts */ - Elements(r->vertices[0])); /* attribs/vert */ -} - -/** - * Prepare the renderer for copying. - */ -VGboolean renderer_copy_begin(struct renderer *renderer, - struct pipe_surface *dst, - VGboolean y0_top, - struct pipe_sampler_view *src) -{ - assert(renderer->state == RENDERER_STATE_INIT); - - /* sanity check */ - if (!renderer_can_support(renderer, - dst->texture, PIPE_BIND_RENDER_TARGET) || - !renderer_can_support(renderer, - src->texture, PIPE_BIND_SAMPLER_VIEW)) - return VG_FALSE; - - cso_save_framebuffer(renderer->cso); - cso_save_viewport(renderer->cso); - cso_save_blend(renderer->cso); - cso_save_samplers(renderer->cso, PIPE_SHADER_FRAGMENT); - cso_save_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT); - cso_save_fragment_shader(renderer->cso); - cso_save_vertex_shader(renderer->cso); - - renderer_set_target(renderer, dst, NULL, y0_top); - - renderer_set_blend(renderer, ~0); - renderer_set_samplers(renderer, 1, &src); - - renderer_set_fs(renderer, RENDERER_FS_TEXTURE); - renderer_set_vs(renderer, RENDERER_VS_TEXTURE); - - renderer_set_mvp(renderer, NULL); - - /* remember the texture size */ - renderer->u.copy.tex_width = src->texture->width0; - renderer->u.copy.tex_height = src->texture->height0; - renderer->state = RENDERER_STATE_COPY; - - return VG_TRUE; -} - -/** - * Draw into the destination rectangle given by (x, y, w, h). The texture is - * sampled from within the rectangle given by (sx, sy, sw, sh). - * - * The coordinates are in surface coordinates. - */ -void renderer_copy(struct renderer *renderer, - VGint x, VGint y, VGint w, VGint h, - VGint sx, VGint sy, VGint sw, VGint sh) -{ - assert(renderer->state == RENDERER_STATE_COPY); - - /* there is no depth buffer for scissoring anyway */ - renderer_quad_pos(renderer, x, y, x + w, y + h, VG_FALSE); - renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh, - renderer->u.copy.tex_width, - renderer->u.copy.tex_height); - - renderer_quad_draw(renderer); -} - -/** - * End copying and restore the states. - */ -void renderer_copy_end(struct renderer *renderer) -{ - assert(renderer->state == RENDERER_STATE_COPY); - - cso_restore_framebuffer(renderer->cso); - cso_restore_viewport(renderer->cso); - cso_restore_blend(renderer->cso); - cso_restore_samplers(renderer->cso, PIPE_SHADER_FRAGMENT); - cso_restore_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT); - cso_restore_fragment_shader(renderer->cso); - cso_restore_vertex_shader(renderer->cso); - - renderer->state = RENDERER_STATE_INIT; -} - -/** - * Prepare the renderer for textured drawing. - */ -VGboolean renderer_drawtex_begin(struct renderer *renderer, - struct pipe_sampler_view *src) -{ - assert(renderer->state == RENDERER_STATE_INIT); - - if (!renderer_can_support(renderer, src->texture, PIPE_BIND_SAMPLER_VIEW)) - return VG_FALSE; - - cso_save_blend(renderer->cso); - cso_save_samplers(renderer->cso, PIPE_SHADER_FRAGMENT); - cso_save_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT); - cso_save_fragment_shader(renderer->cso); - cso_save_vertex_shader(renderer->cso); - - renderer_set_blend(renderer, ~0); - - renderer_set_samplers(renderer, 1, &src); - - renderer_set_fs(renderer, RENDERER_FS_TEXTURE); - renderer_set_vs(renderer, RENDERER_VS_TEXTURE); - - renderer_set_mvp(renderer, NULL); - - /* remember the texture size */ - renderer->u.drawtex.tex_width = src->texture->width0; - renderer->u.drawtex.tex_height = src->texture->height0; - renderer->state = RENDERER_STATE_DRAWTEX; - - return VG_TRUE; -} - -/** - * Draw into the destination rectangle given by (x, y, w, h). The texture is - * sampled from within the rectangle given by (sx, sy, sw, sh). - * - * The coordinates are in surface coordinates. - */ -void renderer_drawtex(struct renderer *renderer, - VGint x, VGint y, VGint w, VGint h, - VGint sx, VGint sy, VGint sw, VGint sh) -{ - assert(renderer->state == RENDERER_STATE_DRAWTEX); - - /* with scissoring */ - renderer_quad_pos(renderer, x, y, x + w, y + h, VG_TRUE); - renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh, - renderer->u.drawtex.tex_width, - renderer->u.drawtex.tex_height); - - renderer_quad_draw(renderer); -} - -/** - * End textured drawing and restore the states. - */ -void renderer_drawtex_end(struct renderer *renderer) -{ - assert(renderer->state == RENDERER_STATE_DRAWTEX); - - cso_restore_blend(renderer->cso); - cso_restore_samplers(renderer->cso, PIPE_SHADER_FRAGMENT); - cso_restore_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT); - cso_restore_fragment_shader(renderer->cso); - cso_restore_vertex_shader(renderer->cso); - - renderer->state = RENDERER_STATE_INIT; -} - -/** - * Prepare the renderer for scissor update. This will reset the depth buffer - * to 1.0f. - */ -VGboolean renderer_scissor_begin(struct renderer *renderer, - VGboolean restore_dsa) -{ - struct pipe_depth_stencil_alpha_state dsa; - - assert(renderer->state == RENDERER_STATE_INIT); - - if (restore_dsa) - cso_save_depth_stencil_alpha(renderer->cso); - cso_save_blend(renderer->cso); - cso_save_fragment_shader(renderer->cso); - - /* enable depth writes */ - memset(&dsa, 0, sizeof(dsa)); - dsa.depth.enabled = 1; - dsa.depth.writemask = 1; - dsa.depth.func = PIPE_FUNC_ALWAYS; - cso_set_depth_stencil_alpha(renderer->cso, &dsa); - - /* disable color writes */ - renderer_set_blend(renderer, 0); - renderer_set_fs(renderer, RENDERER_FS_SCISSOR); - - renderer_set_mvp(renderer, NULL); - - renderer->u.scissor.restore_dsa = restore_dsa; - renderer->state = RENDERER_STATE_SCISSOR; - - /* clear the depth buffer to 1.0f */ - renderer->pipe->clear(renderer->pipe, - PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0f, 0); - - return VG_TRUE; -} - -/** - * Add a scissor rectangle. Depth values inside the rectangle will be set to - * 0.0f. - */ -void renderer_scissor(struct renderer *renderer, - VGint x, VGint y, VGint width, VGint height) -{ - assert(renderer->state == RENDERER_STATE_SCISSOR); - - renderer_quad_pos(renderer, x, y, x + width, y + height, VG_FALSE); - renderer_quad_draw(renderer); -} - -/** - * End scissor update and restore the states. - */ -void renderer_scissor_end(struct renderer *renderer) -{ - assert(renderer->state == RENDERER_STATE_SCISSOR); - - if (renderer->u.scissor.restore_dsa) - cso_restore_depth_stencil_alpha(renderer->cso); - cso_restore_blend(renderer->cso); - cso_restore_fragment_shader(renderer->cso); - - renderer->state = RENDERER_STATE_INIT; -} - -/** - * Prepare the renderer for clearing. - */ -VGboolean renderer_clear_begin(struct renderer *renderer) -{ - assert(renderer->state == RENDERER_STATE_INIT); - - cso_save_blend(renderer->cso); - cso_save_fragment_shader(renderer->cso); - cso_save_vertex_shader(renderer->cso); - - renderer_set_blend(renderer, ~0); - renderer_set_fs(renderer, RENDERER_FS_COLOR); - renderer_set_vs(renderer, RENDERER_VS_COLOR); - - renderer_set_mvp(renderer, NULL); - - renderer->state = RENDERER_STATE_CLEAR; - - return VG_TRUE; -} - -/** - * Clear the framebuffer with the specified region and color. - * - * The coordinates are in surface coordinates. - */ -void renderer_clear(struct renderer *renderer, - VGint x, VGint y, VGint width, VGint height, - const VGfloat color[4]) -{ - VGuint i; - - assert(renderer->state == RENDERER_STATE_CLEAR); - - renderer_quad_pos(renderer, x, y, x + width, y + height, VG_TRUE); - for (i = 0; i < 4; i++) - memcpy(renderer->vertices[i][1], color, sizeof(VGfloat) * 4); - - renderer_quad_draw(renderer); -} - -/** - * End clearing and retore the states. - */ -void renderer_clear_end(struct renderer *renderer) -{ - assert(renderer->state == RENDERER_STATE_CLEAR); - - cso_restore_blend(renderer->cso); - cso_restore_fragment_shader(renderer->cso); - cso_restore_vertex_shader(renderer->cso); - - 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, surf_tmpl; - - assert(renderer->state == RENDERER_STATE_INIT); - - if (!fs) - return VG_FALSE; - if (!renderer_can_support(renderer, dst, PIPE_BIND_RENDER_TARGET)) - return VG_FALSE; - - u_surface_default_template(&surf_tmpl, dst); - surf = renderer->pipe->create_surface(renderer->pipe, dst, &surf_tmpl); - 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, PIPE_SHADER_FRAGMENT); - cso_save_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT); - 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_set_mvp(renderer, NULL); - - 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, PIPE_SHADER_FRAGMENT); - cso_restore_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT); - 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; -} - -/** - * Prepare the renderer for polygon silhouette rendering. - */ -VGboolean renderer_polygon_stencil_begin(struct renderer *renderer, - struct pipe_vertex_element *velem, - VGFillRule rule, - VGboolean restore_dsa) -{ - struct pipe_depth_stencil_alpha_state *dsa; - VGboolean manual_two_sides; - - assert(renderer->state == RENDERER_STATE_INIT); - - cso_save_vertex_elements(renderer->cso); - cso_save_blend(renderer->cso); - cso_save_depth_stencil_alpha(renderer->cso); - - cso_set_vertex_elements(renderer->cso, 1, velem); - - /* disable color writes */ - renderer_set_blend(renderer, 0); - - manual_two_sides = VG_FALSE; - dsa = &renderer->u.polygon_stencil.dsa; - memset(dsa, 0, sizeof(*dsa)); - if (rule == VG_EVEN_ODD) { - dsa->stencil[0].enabled = 1; - dsa->stencil[0].writemask = 1; - dsa->stencil[0].fail_op = PIPE_STENCIL_OP_KEEP; - dsa->stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP; - dsa->stencil[0].zpass_op = PIPE_STENCIL_OP_INVERT; - dsa->stencil[0].func = PIPE_FUNC_ALWAYS; - dsa->stencil[0].valuemask = ~0; - } - else { - assert(rule == VG_NON_ZERO); - - /* front face */ - dsa->stencil[0].enabled = 1; - dsa->stencil[0].writemask = ~0; - dsa->stencil[0].fail_op = PIPE_STENCIL_OP_KEEP; - dsa->stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP; - dsa->stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP; - dsa->stencil[0].func = PIPE_FUNC_ALWAYS; - dsa->stencil[0].valuemask = ~0; - - if (renderer->pipe->screen->get_param(renderer->pipe->screen, - PIPE_CAP_TWO_SIDED_STENCIL)) { - /* back face */ - dsa->stencil[1] = dsa->stencil[0]; - dsa->stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP; - } - else { - manual_two_sides = VG_TRUE; - } - } - cso_set_depth_stencil_alpha(renderer->cso, dsa); - - if (manual_two_sides) - cso_save_rasterizer(renderer->cso); - - renderer->u.polygon_stencil.manual_two_sides = manual_two_sides; - renderer->u.polygon_stencil.restore_dsa = restore_dsa; - renderer->state = RENDERER_STATE_POLYGON_STENCIL; - - return VG_TRUE; -} - -/** - * Render a polygon silhouette to stencil buffer. - */ -void renderer_polygon_stencil(struct renderer *renderer, - struct pipe_vertex_buffer *vbuf, - VGuint mode, VGuint start, VGuint count) -{ - assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL); - - cso_set_vertex_buffers(renderer->cso, 0, 1, vbuf); - - if (!renderer->u.polygon_stencil.manual_two_sides) { - cso_draw_arrays(renderer->cso, mode, start, count); - } - else { - struct pipe_rasterizer_state raster; - struct pipe_depth_stencil_alpha_state dsa; - - raster = renderer->g3d.rasterizer; - dsa = renderer->u.polygon_stencil.dsa; - - /* front */ - raster.cull_face = PIPE_FACE_BACK; - dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP; - - cso_set_rasterizer(renderer->cso, &raster); - cso_set_depth_stencil_alpha(renderer->cso, &dsa); - cso_draw_arrays(renderer->cso, mode, start, count); - - /* back */ - raster.cull_face = PIPE_FACE_FRONT; - dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP; - - cso_set_rasterizer(renderer->cso, &raster); - cso_set_depth_stencil_alpha(renderer->cso, &dsa); - cso_draw_arrays(renderer->cso, mode, start, count); - } -} - -/** - * End polygon silhouette rendering. - */ -void renderer_polygon_stencil_end(struct renderer *renderer) -{ - assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL); - - if (renderer->u.polygon_stencil.manual_two_sides) - cso_restore_rasterizer(renderer->cso); - - cso_restore_vertex_elements(renderer->cso); - - /* restore color writes */ - cso_restore_blend(renderer->cso); - - if (renderer->u.polygon_stencil.restore_dsa) - cso_restore_depth_stencil_alpha(renderer->cso); - - renderer->state = RENDERER_STATE_INIT; -} - -/** - * Prepare the renderer for polygon filling. - */ -VGboolean renderer_polygon_fill_begin(struct renderer *renderer, - VGboolean save_dsa) -{ - struct pipe_depth_stencil_alpha_state dsa; - - assert(renderer->state == RENDERER_STATE_INIT); - - if (save_dsa) - cso_save_depth_stencil_alpha(renderer->cso); - - /* setup stencil ops */ - memset(&dsa, 0, sizeof(dsa)); - dsa.stencil[0].enabled = 1; - dsa.stencil[0].func = PIPE_FUNC_NOTEQUAL; - dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE; - dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE; - dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE; - dsa.stencil[0].valuemask = ~0; - dsa.stencil[0].writemask = ~0; - dsa.depth = renderer->g3d.dsa.depth; - cso_set_depth_stencil_alpha(renderer->cso, &dsa); - - renderer->state = RENDERER_STATE_POLYGON_FILL; - - return VG_TRUE; -} - -/** - * Fill a polygon. - */ -void renderer_polygon_fill(struct renderer *renderer, - VGfloat min_x, VGfloat min_y, - VGfloat max_x, VGfloat max_y) -{ - assert(renderer->state == RENDERER_STATE_POLYGON_FILL); - - renderer_quad_pos(renderer, min_x, min_y, max_x, max_y, VG_TRUE); - renderer_quad_draw(renderer); -} - -/** - * End polygon filling. - */ -void renderer_polygon_fill_end(struct renderer *renderer) -{ - assert(renderer->state == RENDERER_STATE_POLYGON_FILL); - - cso_restore_depth_stencil_alpha(renderer->cso); - - renderer->state = RENDERER_STATE_INIT; -} - -struct renderer * renderer_create(struct vg_context *owner) -{ - struct renderer *renderer; - struct pipe_rasterizer_state *raster; - struct pipe_stencil_ref sr; - VGint i; - - renderer = CALLOC_STRUCT(renderer); - if (!renderer) - return NULL; - - renderer->pipe = owner->pipe; - renderer->cso = owner->cso_context; - - /* init vertex data that doesn't change */ - for (i = 0; i < 4; i++) - renderer->vertices[i][0][3] = 1.0f; /* w */ - - for (i = 0; i < 2; i++) { - renderer->velems[i].src_offset = i * 4 * sizeof(float); - renderer->velems[i].instance_divisor = 0; - renderer->velems[i].vertex_buffer_index = 0; - renderer->velems[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; - } - cso_set_vertex_elements(renderer->cso, 2, renderer->velems); - - /* GL rasterization rules */ - raster = &renderer->g3d.rasterizer; - memset(raster, 0, sizeof(*raster)); - raster->half_pixel_center = 1; - raster->bottom_edge_rule = 1; - raster->depth_clip = 1; - cso_set_rasterizer(renderer->cso, raster); - - /* fixed at 0 */ - memset(&sr, 0, sizeof(sr)); - cso_set_stencil_ref(renderer->cso, &sr); - - renderer_set_vs(renderer, RENDERER_VS_PLAIN); - - renderer->state = RENDERER_STATE_INIT; - - return renderer; -} - -void renderer_destroy(struct renderer *ctx) -{ - int i; - - for (i = 0; i < NUM_RENDERER_VS; i++) { - if (ctx->cached_vs[i]) - cso_delete_vertex_shader(ctx->cso, ctx->cached_vs[i]); - } - for (i = 0; i < NUM_RENDERER_FS; i++) { - if (ctx->cached_fs[i]) - cso_delete_fragment_shader(ctx->cso, ctx->cached_fs[i]); - } - - pipe_resource_reference(&ctx->vs_cbuf, NULL); - pipe_resource_reference(&ctx->fs_cbuf, NULL); - - FREE(ctx); -} - -static void update_clip_state(struct renderer *renderer, - const struct vg_state *state) -{ - struct pipe_depth_stencil_alpha_state *dsa = &renderer->g3d.dsa; - - memset(dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state)); - - if (state->scissoring) { - struct pipe_framebuffer_state *fb = &renderer->g3d.fb; - int i; - - renderer_scissor_begin(renderer, VG_FALSE); - - for (i = 0; i < state->scissor_rects_num; ++i) { - const float x = state->scissor_rects[i * 4 + 0].f; - const float y = state->scissor_rects[i * 4 + 1].f; - const float width = state->scissor_rects[i * 4 + 2].f; - const float height = state->scissor_rects[i * 4 + 3].f; - VGint x0, y0, x1, y1, iw, ih; - - x0 = (VGint) x; - y0 = (VGint) y; - if (x0 < 0) - x0 = 0; - if (y0 < 0) - y0 = 0; - - /* note that x1 and y1 are exclusive */ - x1 = (VGint) ceilf(x + width); - y1 = (VGint) ceilf(y + height); - if (x1 > fb->width) - x1 = fb->width; - if (y1 > fb->height) - y1 = fb->height; - - iw = x1 - x0; - ih = y1 - y0; - if (iw > 0 && ih> 0 ) - renderer_scissor(renderer, x0, y0, iw, ih); - } - - renderer_scissor_end(renderer); - - dsa->depth.enabled = 1; /* glEnable(GL_DEPTH_TEST); */ - dsa->depth.writemask = 0;/*glDepthMask(FALSE);*/ - dsa->depth.func = PIPE_FUNC_GEQUAL; - } -} - -static void renderer_validate_blend(struct renderer *renderer, - const struct vg_state *state, - enum pipe_format fb_format) -{ - struct pipe_blend_state blend; - - memset(&blend, 0, sizeof(blend)); - blend.rt[0].colormask = PIPE_MASK_RGBA; - 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; - - /* TODO alpha masking happens after blending? */ - - switch (state->blend_mode) { - case VG_BLEND_SRC: - 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; - break; - case VG_BLEND_SRC_OVER: - /* use the blend state only when there is no alpha channel */ - if (!util_format_has_alpha(fb_format)) { - blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA; - blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; - blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; - blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; - blend.rt[0].blend_enable = 1; - } - break; - case VG_BLEND_SRC_IN: - blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; - blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_DST_ALPHA; - blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; - blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; - blend.rt[0].blend_enable = 1; - break; - case VG_BLEND_DST_IN: - blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ZERO; - blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO; - blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE; - blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA; - blend.rt[0].blend_enable = 1; - break; - case VG_BLEND_DST_OVER: - case VG_BLEND_MULTIPLY: - case VG_BLEND_SCREEN: - case VG_BLEND_DARKEN: - case VG_BLEND_LIGHTEN: - case VG_BLEND_ADDITIVE: - /* need a shader */ - break; - default: - assert(!"not implemented blend mode"); - break; - } - - cso_set_blend(renderer->cso, &blend); -} - -/** - * Propogate OpenVG state changes to the renderer. Only framebuffer, blending - * and scissoring states are relevant here. - */ -void renderer_validate(struct renderer *renderer, - VGbitfield dirty, - const struct st_framebuffer *stfb, - const struct vg_state *state) -{ - assert(renderer->state == RENDERER_STATE_INIT); - - dirty |= renderer->dirty; - renderer->dirty = 0; - - if (dirty & FRAMEBUFFER_DIRTY) { - struct pipe_framebuffer_state *fb = &renderer->g3d.fb; - struct matrix *proj = &renderer->projection; - - memset(fb, 0, sizeof(struct pipe_framebuffer_state)); - fb->width = stfb->width; - fb->height = stfb->height; - fb->nr_cbufs = 1; - fb->cbufs[0] = stfb->strb->surface; - fb->zsbuf = stfb->dsrb->surface; - - cso_set_framebuffer(renderer->cso, fb); - vg_set_viewport(renderer, VEGA_Y0_BOTTOM); - - matrix_load_identity(proj); - matrix_translate(proj, -1.0f, -1.0f); - matrix_scale(proj, 2.0f / fb->width, 2.0f / fb->height); - - /* we also got a new depth buffer */ - if (dirty & DEPTH_STENCIL_DIRTY) { - renderer->pipe->clear(renderer->pipe, - PIPE_CLEAR_DEPTHSTENCIL, NULL, 0.0, 0); - } - } - - /* must be last because it renders to the depth buffer*/ - if (dirty & DEPTH_STENCIL_DIRTY) { - update_clip_state(renderer, state); - cso_set_depth_stencil_alpha(renderer->cso, &renderer->g3d.dsa); - } - - if (dirty & BLEND_DIRTY) - renderer_validate_blend(renderer, state, stfb->strb->format); -} - -/** - * Prepare the renderer for OpenVG pipeline. - */ -void renderer_validate_for_shader(struct renderer *renderer, - const struct pipe_sampler_state **samplers, - struct pipe_sampler_view **views, - VGint num_samplers, - const struct matrix *modelview, - void *fs, - const void *const_buffer, - VGint const_buffer_len) -{ - struct matrix mvp = renderer->projection; - - /* will be used in POLYGON_STENCIL and POLYGON_FILL */ - matrix_mult(&mvp, modelview); - renderer_set_mvp(renderer, &mvp); - - renderer_set_custom_fs(renderer, fs, - samplers, views, num_samplers, - const_buffer, const_buffer_len); -} - -void renderer_validate_for_mask_rendering(struct renderer *renderer, - struct pipe_surface *dst, - const struct matrix *modelview) -{ - struct matrix mvp = renderer->projection; - - /* will be used in POLYGON_STENCIL and POLYGON_FILL */ - matrix_mult(&mvp, modelview); - renderer_set_mvp(renderer, &mvp); - - renderer_set_target(renderer, dst, renderer->g3d.fb.zsbuf, VG_FALSE); - renderer_set_blend(renderer, ~0); - renderer_set_fs(renderer, RENDERER_FS_WHITE); - - /* set internal dirty flags (hacky!) */ - renderer->dirty = FRAMEBUFFER_DIRTY | BLEND_DIRTY; -} - -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_sampler_view view_templ; - struct pipe_sampler_view *view; - struct pipe_box src_box; - struct pipe_resource texTemp, *tex; - const struct pipe_framebuffer_state *fb = &ctx->g3d.fb; - 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, - 0, PIPE_BIND_SAMPLER_VIEW)); - assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, - 0, PIPE_BIND_SAMPLER_VIEW)); - assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, - 0, PIPE_BIND_RENDER_TARGET)); - - /* - * 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; - texTemp.array_size = 1; - texTemp.bind = PIPE_BIND_SAMPLER_VIEW; - - tex = screen->resource_create(screen, &texTemp); - if (!tex) - return; - - u_sampler_view_default_template(&view_templ, tex, tex->format); - view = pipe->create_sampler_view(pipe, tex, &view_templ); - - if (!view) - return; - - u_box_2d_zslice(srcLeft, srcTop, src->u.tex.first_layer, srcW, srcH, &src_box); - - pipe->resource_copy_region(pipe, - tex, 0, 0, 0, 0, /* dest */ - src->texture, 0, &src_box); - - assert(floatsEqual(z, 0.0f)); - - /* draw */ - if (fb->cbufs[0] == dst) { - /* transform back to surface coordinates */ - dstY0 = dst->height - dstY0; - dstY1 = dst->height - dstY1; - - if (renderer_drawtex_begin(ctx, view)) { - renderer_drawtex(ctx, - dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0, - 0, 0, view->texture->width0, view->texture->height0); - renderer_drawtex_end(ctx); - } - } - else { - if (renderer_copy_begin(ctx, dst, VG_TRUE, view)) { - renderer_copy(ctx, - dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0, - 0, 0, view->texture->width0, view->texture->height0); - renderer_copy_end(ctx); - } - } -} - -void renderer_texture_quad(struct renderer *r, - struct pipe_resource *tex, - VGfloat x1offset, VGfloat y1offset, - VGfloat x2offset, VGfloat y2offset, - VGfloat x1, VGfloat y1, - VGfloat x2, VGfloat y2, - VGfloat x3, VGfloat y3, - VGfloat x4, VGfloat y4) -{ - const VGfloat z = 0.0f; - - assert(r->state == RENDERER_STATE_INIT); - assert(tex->width0 != 0); - assert(tex->height0 != 0); - - cso_save_vertex_shader(r->cso); - - renderer_set_vs(r, RENDERER_VS_TEXTURE); - - /* manually set up positions */ - r->vertices[0][0][0] = x1; - r->vertices[0][0][1] = y1; - r->vertices[0][0][2] = z; - - r->vertices[1][0][0] = x2; - r->vertices[1][0][1] = y2; - r->vertices[1][0][2] = z; - - r->vertices[2][0][0] = x3; - r->vertices[2][0][1] = y3; - r->vertices[2][0][2] = z; - - r->vertices[3][0][0] = x4; - r->vertices[3][0][1] = y4; - r->vertices[3][0][2] = z; - - /* texcoords */ - renderer_quad_texcoord(r, x1offset, y1offset, - x2offset, y2offset, tex->width0, tex->height0); - - renderer_quad_draw(r); - - cso_restore_vertex_shader(r->cso); -} |