1 /************************************************************************** 2 * 3 * Copyright 2007 VMware, Inc. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 #include "util/u_rect.h" 29 #include "util/u_surface.h" 30 #include "lp_context.h" 31 #include "lp_flush.h" 32 #include "lp_limits.h" 33 #include "lp_surface.h" 34 #include "lp_texture.h" 35 #include "lp_query.h" 36 37 38 static void 39 lp_resource_copy(struct pipe_context *pipe, 40 struct pipe_resource *dst, unsigned dst_level, 41 unsigned dstx, unsigned dsty, unsigned dstz, 42 struct pipe_resource *src, unsigned src_level, 43 const struct pipe_box *src_box) 44 { 45 llvmpipe_flush_resource(pipe, 46 dst, dst_level, 47 FALSE, /* read_only */ 48 TRUE, /* cpu_access */ 49 FALSE, /* do_not_block */ 50 "blit dest"); 51 52 llvmpipe_flush_resource(pipe, 53 src, src_level, 54 TRUE, /* read_only */ 55 TRUE, /* cpu_access */ 56 FALSE, /* do_not_block */ 57 "blit src"); 58 59 util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz, 60 src, src_level, src_box); 61 } 62 63 64 static void lp_blit(struct pipe_context *pipe, 65 const struct pipe_blit_info *blit_info) 66 { 67 struct llvmpipe_context *lp = llvmpipe_context(pipe); 68 struct pipe_blit_info info = *blit_info; 69 70 if (blit_info->render_condition_enable && !llvmpipe_check_render_cond(lp)) 71 return; 72 73 if (info.src.resource->nr_samples > 1 && 74 info.dst.resource->nr_samples <= 1 && 75 !util_format_is_depth_or_stencil(info.src.resource->format) && 76 !util_format_is_pure_integer(info.src.resource->format)) { 77 debug_printf("llvmpipe: color resolve unimplemented\n"); 78 return; 79 } 80 81 if (util_try_blit_via_copy_region(pipe, &info)) { 82 return; /* done */ 83 } 84 85 if (!util_blitter_is_blit_supported(lp->blitter, &info)) { 86 debug_printf("llvmpipe: blit unsupported %s -> %s\n", 87 util_format_short_name(info.src.resource->format), 88 util_format_short_name(info.dst.resource->format)); 89 return; 90 } 91 92 /* XXX turn off occlusion and streamout queries */ 93 94 util_blitter_save_vertex_buffer_slot(lp->blitter, lp->vertex_buffer); 95 util_blitter_save_vertex_elements(lp->blitter, (void*)lp->velems); 96 util_blitter_save_vertex_shader(lp->blitter, (void*)lp->vs); 97 util_blitter_save_geometry_shader(lp->blitter, (void*)lp->gs); 98 util_blitter_save_so_targets(lp->blitter, lp->num_so_targets, 99 (struct pipe_stream_output_target**)lp->so_targets); 100 util_blitter_save_rasterizer(lp->blitter, (void*)lp->rasterizer); 101 util_blitter_save_viewport(lp->blitter, &lp->viewports[0]); 102 util_blitter_save_scissor(lp->blitter, &lp->scissors[0]); 103 util_blitter_save_fragment_shader(lp->blitter, lp->fs); 104 util_blitter_save_blend(lp->blitter, (void*)lp->blend); 105 util_blitter_save_depth_stencil_alpha(lp->blitter, (void*)lp->depth_stencil); 106 util_blitter_save_stencil_ref(lp->blitter, &lp->stencil_ref); 107 /*util_blitter_save_sample_mask(sp->blitter, lp->sample_mask);*/ 108 util_blitter_save_framebuffer(lp->blitter, &lp->framebuffer); 109 util_blitter_save_fragment_sampler_states(lp->blitter, 110 lp->num_samplers[PIPE_SHADER_FRAGMENT], 111 (void**)lp->samplers[PIPE_SHADER_FRAGMENT]); 112 util_blitter_save_fragment_sampler_views(lp->blitter, 113 lp->num_sampler_views[PIPE_SHADER_FRAGMENT], 114 lp->sampler_views[PIPE_SHADER_FRAGMENT]); 115 util_blitter_save_render_condition(lp->blitter, lp->render_cond_query, 116 lp->render_cond_cond, lp->render_cond_mode); 117 util_blitter_blit(lp->blitter, &info); 118 } 119 120 121 static void 122 lp_flush_resource(struct pipe_context *ctx, struct pipe_resource *resource) 123 { 124 } 125 126 127 static struct pipe_surface * 128 llvmpipe_create_surface(struct pipe_context *pipe, 129 struct pipe_resource *pt, 130 const struct pipe_surface *surf_tmpl) 131 { 132 struct pipe_surface *ps; 133 134 if (!(pt->bind & (PIPE_BIND_DEPTH_STENCIL | PIPE_BIND_RENDER_TARGET))) { 135 debug_printf("Illegal surface creation without bind flag\n"); 136 if (util_format_is_depth_or_stencil(surf_tmpl->format)) { 137 pt->bind |= PIPE_BIND_DEPTH_STENCIL; 138 } 139 else { 140 pt->bind |= PIPE_BIND_RENDER_TARGET; 141 } 142 } 143 144 ps = CALLOC_STRUCT(pipe_surface); 145 if (ps) { 146 pipe_reference_init(&ps->reference, 1); 147 pipe_resource_reference(&ps->texture, pt); 148 ps->context = pipe; 149 ps->format = surf_tmpl->format; 150 if (llvmpipe_resource_is_texture(pt)) { 151 assert(surf_tmpl->u.tex.level <= pt->last_level); 152 assert(surf_tmpl->u.tex.first_layer <= surf_tmpl->u.tex.last_layer); 153 ps->width = u_minify(pt->width0, surf_tmpl->u.tex.level); 154 ps->height = u_minify(pt->height0, surf_tmpl->u.tex.level); 155 ps->u.tex.level = surf_tmpl->u.tex.level; 156 ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer; 157 ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer; 158 } 159 else { 160 /* setting width as number of elements should get us correct renderbuffer width */ 161 ps->width = surf_tmpl->u.buf.last_element - surf_tmpl->u.buf.first_element + 1; 162 ps->height = pt->height0; 163 ps->u.buf.first_element = surf_tmpl->u.buf.first_element; 164 ps->u.buf.last_element = surf_tmpl->u.buf.last_element; 165 assert(ps->u.buf.first_element <= ps->u.buf.last_element); 166 assert(util_format_get_blocksize(surf_tmpl->format) * 167 (ps->u.buf.last_element + 1) <= pt->width0); 168 } 169 } 170 return ps; 171 } 172 173 174 static void 175 llvmpipe_surface_destroy(struct pipe_context *pipe, 176 struct pipe_surface *surf) 177 { 178 /* Effectively do the texture_update work here - if texture images 179 * needed post-processing to put them into hardware layout, this is 180 * where it would happen. For llvmpipe, nothing to do. 181 */ 182 assert(surf->texture); 183 pipe_resource_reference(&surf->texture, NULL); 184 FREE(surf); 185 } 186 187 188 static void 189 llvmpipe_clear_render_target(struct pipe_context *pipe, 190 struct pipe_surface *dst, 191 const union pipe_color_union *color, 192 unsigned dstx, unsigned dsty, 193 unsigned width, unsigned height, 194 bool render_condition_enabled) 195 { 196 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); 197 198 if (render_condition_enabled && !llvmpipe_check_render_cond(llvmpipe)) 199 return; 200 201 util_clear_render_target(pipe, dst, color, 202 dstx, dsty, width, height); 203 } 204 205 206 static void 207 llvmpipe_clear_depth_stencil(struct pipe_context *pipe, 208 struct pipe_surface *dst, 209 unsigned clear_flags, 210 double depth, 211 unsigned stencil, 212 unsigned dstx, unsigned dsty, 213 unsigned width, unsigned height, 214 bool render_condition_enabled) 215 { 216 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); 217 218 if (render_condition_enabled && !llvmpipe_check_render_cond(llvmpipe)) 219 return; 220 221 util_clear_depth_stencil(pipe, dst, clear_flags, 222 depth, stencil, 223 dstx, dsty, width, height); 224 } 225 226 227 void 228 llvmpipe_init_surface_functions(struct llvmpipe_context *lp) 229 { 230 lp->pipe.clear_render_target = llvmpipe_clear_render_target; 231 lp->pipe.clear_depth_stencil = llvmpipe_clear_depth_stencil; 232 lp->pipe.create_surface = llvmpipe_create_surface; 233 lp->pipe.surface_destroy = llvmpipe_surface_destroy; 234 /* These two are not actually functions dealing with surfaces */ 235 lp->pipe.resource_copy_region = lp_resource_copy; 236 lp->pipe.blit = lp_blit; 237 lp->pipe.flush_resource = lp_flush_resource; 238 } 239