shader.c revision f914cd1796845164109c837a111c39ba64852ad4
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 35#include "pipe/p_context.h" 36#include "pipe/p_screen.h" 37#include "pipe/p_state.h" 38#include "util/u_inlines.h" 39#include "util/u_memory.h" 40 41#define MAX_CONSTANTS 20 42 43struct shader { 44 struct vg_context *context; 45 46 VGboolean masking; 47 struct vg_paint *paint; 48 struct vg_image *image; 49 50 VGboolean drawing_image; 51 VGImageMode image_mode; 52 53 float constants[MAX_CONSTANTS]; 54 struct pipe_resource *cbuf; 55 struct pipe_shader_state fs_state; 56 void *fs; 57}; 58 59struct shader * shader_create(struct vg_context *ctx) 60{ 61 struct shader *shader = 0; 62 63 shader = CALLOC_STRUCT(shader); 64 shader->context = ctx; 65 66 return shader; 67} 68 69void shader_destroy(struct shader *shader) 70{ 71 FREE(shader); 72} 73 74void shader_set_masking(struct shader *shader, VGboolean set) 75{ 76 shader->masking = set; 77} 78 79VGboolean shader_is_masking(struct shader *shader) 80{ 81 return shader->masking; 82} 83 84void shader_set_paint(struct shader *shader, struct vg_paint *paint) 85{ 86 shader->paint = paint; 87} 88 89struct vg_paint * shader_paint(struct shader *shader) 90{ 91 return shader->paint; 92} 93 94 95static void setup_constant_buffer(struct shader *shader) 96{ 97 struct vg_context *ctx = shader->context; 98 struct pipe_context *pipe = shader->context->pipe; 99 struct pipe_resource **cbuf = &shader->cbuf; 100 VGint param_bytes = paint_constant_buffer_size(shader->paint); 101 float temp_buf[MAX_CONSTANTS]; 102 103 assert(param_bytes <= sizeof(temp_buf)); 104 paint_fill_constant_buffer(shader->paint, temp_buf); 105 106 if (*cbuf == NULL || 107 memcmp(temp_buf, shader->constants, param_bytes) != 0) 108 { 109 pipe_resource_reference(cbuf, NULL); 110 111 memcpy(shader->constants, temp_buf, param_bytes); 112 *cbuf = pipe_user_buffer_create(pipe->screen, 113 &shader->constants, 114 sizeof(shader->constants), 115 PIPE_BIND_VERTEX_BUFFER); 116 } 117 118 ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, *cbuf); 119} 120 121static VGint blend_bind_samplers(struct vg_context *ctx, 122 struct pipe_sampler_state **samplers, 123 struct pipe_sampler_view **sampler_views) 124{ 125 VGBlendMode bmode = ctx->state.vg.blend_mode; 126 127 if (bmode == VG_BLEND_MULTIPLY || 128 bmode == VG_BLEND_SCREEN || 129 bmode == VG_BLEND_DARKEN || 130 bmode == VG_BLEND_LIGHTEN) { 131 struct st_framebuffer *stfb = ctx->draw_buffer; 132 133 vg_prepare_blend_surface(ctx); 134 135 samplers[2] = &ctx->blend_sampler; 136 sampler_views[2] = stfb->blend_texture_view; 137 138 if (!samplers[0] || !sampler_views[0]) { 139 samplers[0] = samplers[2]; 140 sampler_views[0] = sampler_views[2]; 141 } 142 if (!samplers[1] || !sampler_views[1]) { 143 samplers[1] = samplers[0]; 144 sampler_views[1] = sampler_views[0]; 145 } 146 147 return 1; 148 } 149 return 0; 150} 151 152static void setup_samplers(struct shader *shader) 153{ 154 struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; 155 struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; 156 struct vg_context *ctx = shader->context; 157 /* a little wonky: we use the num as a boolean that just says 158 * whether any sampler/textures have been set. the actual numbering 159 * for samplers is always the same: 160 * 0 - paint sampler/texture for gradient/pattern 161 * 1 - mask sampler/texture 162 * 2 - blend sampler/texture 163 * 3 - image sampler/texture 164 * */ 165 VGint num = 0; 166 167 samplers[0] = NULL; 168 samplers[1] = NULL; 169 samplers[2] = NULL; 170 samplers[3] = NULL; 171 sampler_views[0] = NULL; 172 sampler_views[1] = NULL; 173 sampler_views[2] = NULL; 174 sampler_views[3] = NULL; 175 176 num += paint_bind_samplers(shader->paint, samplers, sampler_views); 177 num += mask_bind_samplers(samplers, sampler_views); 178 num += blend_bind_samplers(ctx, samplers, sampler_views); 179 if (shader->drawing_image && shader->image) 180 num += image_bind_samplers(shader->image, samplers, sampler_views); 181 182 if (num) { 183 cso_set_samplers(ctx->cso_context, 4, (const struct pipe_sampler_state **)samplers); 184 cso_set_fragment_sampler_views(ctx->cso_context, 4, sampler_views); 185 } 186} 187 188static INLINE VGboolean is_format_bw(struct shader *shader) 189{ 190#if 0 191 struct vg_context *ctx = shader->context; 192 struct st_framebuffer *stfb = ctx->draw_buffer; 193#endif 194 195 if (shader->drawing_image && shader->image) { 196 if (shader->image->format == VG_BW_1) 197 return VG_TRUE; 198 } 199 200 return VG_FALSE; 201} 202 203static void setup_shader_program(struct shader *shader) 204{ 205 struct vg_context *ctx = shader->context; 206 VGint shader_id = 0; 207 VGBlendMode blend_mode = ctx->state.vg.blend_mode; 208 VGboolean black_white = is_format_bw(shader); 209 210 /* 1st stage: fill */ 211 if (!shader->drawing_image || 212 (shader->image_mode == VG_DRAW_IMAGE_MULTIPLY || shader->image_mode == VG_DRAW_IMAGE_STENCIL)) { 213 switch(paint_type(shader->paint)) { 214 case VG_PAINT_TYPE_COLOR: 215 shader_id |= VEGA_SOLID_FILL_SHADER; 216 break; 217 case VG_PAINT_TYPE_LINEAR_GRADIENT: 218 shader_id |= VEGA_LINEAR_GRADIENT_SHADER; 219 break; 220 case VG_PAINT_TYPE_RADIAL_GRADIENT: 221 shader_id |= VEGA_RADIAL_GRADIENT_SHADER; 222 break; 223 case VG_PAINT_TYPE_PATTERN: 224 shader_id |= VEGA_PATTERN_SHADER; 225 break; 226 227 default: 228 abort(); 229 } 230 } 231 232 /* second stage image */ 233 if (shader->drawing_image) { 234 switch(shader->image_mode) { 235 case VG_DRAW_IMAGE_NORMAL: 236 shader_id |= VEGA_IMAGE_NORMAL_SHADER; 237 break; 238 case VG_DRAW_IMAGE_MULTIPLY: 239 shader_id |= VEGA_IMAGE_MULTIPLY_SHADER; 240 break; 241 case VG_DRAW_IMAGE_STENCIL: 242 shader_id |= VEGA_IMAGE_STENCIL_SHADER; 243 break; 244 default: 245 debug_printf("Unknown image mode!"); 246 } 247 } 248 249 if (shader->masking) 250 shader_id |= VEGA_MASK_SHADER; 251 252 switch(blend_mode) { 253 case VG_BLEND_MULTIPLY: 254 shader_id |= VEGA_BLEND_MULTIPLY_SHADER; 255 break; 256 case VG_BLEND_SCREEN: 257 shader_id |= VEGA_BLEND_SCREEN_SHADER; 258 break; 259 case VG_BLEND_DARKEN: 260 shader_id |= VEGA_BLEND_DARKEN_SHADER; 261 break; 262 case VG_BLEND_LIGHTEN: 263 shader_id |= VEGA_BLEND_LIGHTEN_SHADER; 264 break; 265 default: 266 /* handled by pipe_blend_state */ 267 break; 268 } 269 270 if (black_white) 271 shader_id |= VEGA_BW_SHADER; 272 273 shader->fs = shaders_cache_fill(ctx->sc, shader_id); 274 cso_set_fragment_shader_handle(ctx->cso_context, shader->fs); 275} 276 277 278void shader_bind(struct shader *shader) 279{ 280 /* first resolve the real paint type */ 281 paint_resolve_type(shader->paint); 282 283 setup_constant_buffer(shader); 284 setup_samplers(shader); 285 setup_shader_program(shader); 286} 287 288void shader_set_image_mode(struct shader *shader, VGImageMode image_mode) 289{ 290 shader->image_mode = image_mode; 291} 292 293VGImageMode shader_image_mode(struct shader *shader) 294{ 295 return shader->image_mode; 296} 297 298void shader_set_drawing_image(struct shader *shader, VGboolean drawing_image) 299{ 300 shader->drawing_image = drawing_image; 301} 302 303VGboolean shader_drawing_image(struct shader *shader) 304{ 305 return shader->drawing_image; 306} 307 308void shader_set_image(struct shader *shader, struct vg_image *img) 309{ 310 shader->image = img; 311} 312