shader.c revision ee0f1ab923cc52b5eeacc47a749561d1c7216207
1/************************************************************************** 2 * 3 * Copyright 2009 VMware, Inc. All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sub license, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial portions 15 * of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 20 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 * 25 **************************************************************************/ 26 27#include "shader.h" 28 29#include "vg_context.h" 30#include "shaders_cache.h" 31#include "paint.h" 32#include "mask.h" 33#include "image.h" 34#include "renderer.h" 35 36#include "pipe/p_context.h" 37#include "pipe/p_screen.h" 38#include "pipe/p_state.h" 39#include "util/u_inlines.h" 40#include "util/u_memory.h" 41 42#define MAX_CONSTANTS 20 43 44struct shader { 45 struct vg_context *context; 46 47 VGboolean masking; 48 struct vg_paint *paint; 49 struct vg_image *image; 50 51 VGboolean drawing_image; 52 VGImageMode image_mode; 53 54 float constants[MAX_CONSTANTS]; 55 struct pipe_resource *cbuf; 56 struct pipe_shader_state fs_state; 57 void *fs; 58}; 59 60struct shader * shader_create(struct vg_context *ctx) 61{ 62 struct shader *shader = 0; 63 64 shader = CALLOC_STRUCT(shader); 65 shader->context = ctx; 66 67 return shader; 68} 69 70void shader_destroy(struct shader *shader) 71{ 72 FREE(shader); 73} 74 75void shader_set_masking(struct shader *shader, VGboolean set) 76{ 77 shader->masking = set; 78} 79 80VGboolean shader_is_masking(struct shader *shader) 81{ 82 return shader->masking; 83} 84 85void shader_set_paint(struct shader *shader, struct vg_paint *paint) 86{ 87 shader->paint = paint; 88} 89 90struct vg_paint * shader_paint(struct shader *shader) 91{ 92 return shader->paint; 93} 94 95static VGint setup_constant_buffer(struct shader *shader) 96{ 97 VGint param_bytes = paint_constant_buffer_size(shader->paint); 98 99 assert(param_bytes <= sizeof(shader->constants)); 100 paint_fill_constant_buffer(shader->paint, shader->constants); 101 102 return param_bytes; 103} 104 105static VGint blend_bind_samplers(struct vg_context *ctx, 106 struct pipe_sampler_state **samplers, 107 struct pipe_sampler_view **sampler_views) 108{ 109 VGBlendMode bmode = ctx->state.vg.blend_mode; 110 111 if (bmode == VG_BLEND_MULTIPLY || 112 bmode == VG_BLEND_SCREEN || 113 bmode == VG_BLEND_DARKEN || 114 bmode == VG_BLEND_LIGHTEN) { 115 struct st_framebuffer *stfb = ctx->draw_buffer; 116 117 vg_prepare_blend_surface(ctx); 118 119 samplers[2] = &ctx->blend_sampler; 120 sampler_views[2] = stfb->blend_texture_view; 121 122 if (!samplers[0] || !sampler_views[0]) { 123 samplers[0] = samplers[2]; 124 sampler_views[0] = sampler_views[2]; 125 } 126 if (!samplers[1] || !sampler_views[1]) { 127 samplers[1] = samplers[0]; 128 sampler_views[1] = sampler_views[0]; 129 } 130 131 return 1; 132 } 133 return 0; 134} 135 136static VGint setup_samplers(struct shader *shader, 137 struct pipe_sampler_state **samplers, 138 struct pipe_sampler_view **sampler_views) 139{ 140 struct vg_context *ctx = shader->context; 141 /* a little wonky: we use the num as a boolean that just says 142 * whether any sampler/textures have been set. the actual numbering 143 * for samplers is always the same: 144 * 0 - paint sampler/texture for gradient/pattern 145 * 1 - mask sampler/texture 146 * 2 - blend sampler/texture 147 * 3 - image sampler/texture 148 * */ 149 VGint num = 0; 150 151 samplers[0] = NULL; 152 samplers[1] = NULL; 153 samplers[2] = NULL; 154 samplers[3] = NULL; 155 sampler_views[0] = NULL; 156 sampler_views[1] = NULL; 157 sampler_views[2] = NULL; 158 sampler_views[3] = NULL; 159 160 num += paint_bind_samplers(shader->paint, samplers, sampler_views); 161 num += mask_bind_samplers(samplers, sampler_views); 162 num += blend_bind_samplers(ctx, samplers, sampler_views); 163 if (shader->drawing_image && shader->image) 164 num += image_bind_samplers(shader->image, samplers, sampler_views); 165 166 return (num) ? 4 : 0; 167} 168 169static INLINE VGboolean is_format_bw(struct shader *shader) 170{ 171#if 0 172 struct vg_context *ctx = shader->context; 173 struct st_framebuffer *stfb = ctx->draw_buffer; 174#endif 175 176 if (shader->drawing_image && shader->image) { 177 if (shader->image->format == VG_BW_1) 178 return VG_TRUE; 179 } 180 181 return VG_FALSE; 182} 183 184static void setup_shader_program(struct shader *shader) 185{ 186 struct vg_context *ctx = shader->context; 187 VGint shader_id = 0; 188 VGBlendMode blend_mode = ctx->state.vg.blend_mode; 189 VGboolean black_white = is_format_bw(shader); 190 191 /* 1st stage: fill */ 192 if (!shader->drawing_image || 193 (shader->image_mode == VG_DRAW_IMAGE_MULTIPLY || shader->image_mode == VG_DRAW_IMAGE_STENCIL)) { 194 switch(paint_type(shader->paint)) { 195 case VG_PAINT_TYPE_COLOR: 196 shader_id |= VEGA_SOLID_FILL_SHADER; 197 break; 198 case VG_PAINT_TYPE_LINEAR_GRADIENT: 199 shader_id |= VEGA_LINEAR_GRADIENT_SHADER; 200 break; 201 case VG_PAINT_TYPE_RADIAL_GRADIENT: 202 shader_id |= VEGA_RADIAL_GRADIENT_SHADER; 203 break; 204 case VG_PAINT_TYPE_PATTERN: 205 shader_id |= VEGA_PATTERN_SHADER; 206 break; 207 208 default: 209 abort(); 210 } 211 } 212 213 /* second stage image */ 214 if (shader->drawing_image) { 215 switch(shader->image_mode) { 216 case VG_DRAW_IMAGE_NORMAL: 217 shader_id |= VEGA_IMAGE_NORMAL_SHADER; 218 break; 219 case VG_DRAW_IMAGE_MULTIPLY: 220 shader_id |= VEGA_IMAGE_MULTIPLY_SHADER; 221 break; 222 case VG_DRAW_IMAGE_STENCIL: 223 shader_id |= VEGA_IMAGE_STENCIL_SHADER; 224 break; 225 default: 226 debug_printf("Unknown image mode!"); 227 } 228 } 229 230 if (shader->masking) 231 shader_id |= VEGA_MASK_SHADER; 232 233 switch(blend_mode) { 234 case VG_BLEND_MULTIPLY: 235 shader_id |= VEGA_BLEND_MULTIPLY_SHADER; 236 break; 237 case VG_BLEND_SCREEN: 238 shader_id |= VEGA_BLEND_SCREEN_SHADER; 239 break; 240 case VG_BLEND_DARKEN: 241 shader_id |= VEGA_BLEND_DARKEN_SHADER; 242 break; 243 case VG_BLEND_LIGHTEN: 244 shader_id |= VEGA_BLEND_LIGHTEN_SHADER; 245 break; 246 default: 247 /* handled by pipe_blend_state */ 248 break; 249 } 250 251 if (black_white) 252 shader_id |= VEGA_BW_SHADER; 253 254 shader->fs = shaders_cache_fill(ctx->sc, shader_id); 255} 256 257 258void shader_bind(struct shader *shader) 259{ 260 struct vg_context *ctx = shader->context; 261 struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; 262 struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; 263 VGint num_samplers, param_bytes; 264 265 /* first resolve the real paint type */ 266 paint_resolve_type(shader->paint); 267 268 num_samplers = setup_samplers(shader, samplers, sampler_views); 269 param_bytes = setup_constant_buffer(shader); 270 setup_shader_program(shader); 271 272 renderer_validate_for_shader(ctx->renderer, 273 (const struct pipe_sampler_state **) samplers, 274 sampler_views, num_samplers, 275 shader->fs, (const void *) shader->constants, param_bytes); 276} 277 278void shader_set_image_mode(struct shader *shader, VGImageMode image_mode) 279{ 280 shader->image_mode = image_mode; 281} 282 283VGImageMode shader_image_mode(struct shader *shader) 284{ 285 return shader->image_mode; 286} 287 288void shader_set_drawing_image(struct shader *shader, VGboolean drawing_image) 289{ 290 shader->drawing_image = drawing_image; 291} 292 293VGboolean shader_drawing_image(struct shader *shader) 294{ 295 return shader->drawing_image; 296} 297 298void shader_set_image(struct shader *shader, struct vg_image *img) 299{ 300 shader->image = img; 301} 302