1/************************************************************************** 2 * 3 * Copyright 2009 VMware, Inc. 4 * Copyright 2007 VMware, Inc. 5 * All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the 9 * "Software"), to deal in the Software without restriction, including 10 * without limitation the rights to use, copy, modify, merge, publish, 11 * distribute, sub license, and/or sell copies of the Software, and to 12 * permit persons to whom the Software is furnished to do so, subject to 13 * the following conditions: 14 * 15 * The above copyright notice and this permission notice (including the 16 * next paragraph) shall be included in all copies or substantial portions 17 * of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 * 27 **************************************************************************/ 28 29/** 30 * @author Jose Fonseca <jfonseca@vmware.com> 31 * @author Keith Whitwell <keithw@vmware.com> 32 */ 33 34#include "util/u_memory.h" 35#include "util/u_math.h" 36#include "util/u_dump.h" 37#include "draw/draw_context.h" 38#include "lp_screen.h" 39#include "lp_context.h" 40#include "lp_state.h" 41#include "lp_debug.h" 42 43 44static void * 45llvmpipe_create_blend_state(struct pipe_context *pipe, 46 const struct pipe_blend_state *blend) 47{ 48 struct pipe_blend_state *state = mem_dup(blend, sizeof *blend); 49 50 if (LP_PERF & PERF_NO_BLEND) { 51 state->independent_blend_enable = 0; 52 for (unsigned i = 0; i < PIPE_MAX_COLOR_BUFS; i++) 53 state->rt[i].blend_enable = 0; 54 } 55 56 return state; 57} 58 59 60static void 61llvmpipe_bind_blend_state(struct pipe_context *pipe, void *blend) 62{ 63 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); 64 65 if (llvmpipe->blend == blend) 66 return; 67 68 draw_flush(llvmpipe->draw); 69 70 llvmpipe->blend = blend; 71 72 llvmpipe->dirty |= LP_NEW_BLEND; 73} 74 75 76static void 77llvmpipe_delete_blend_state(struct pipe_context *pipe, void *blend) 78{ 79 FREE(blend); 80} 81 82 83static void 84llvmpipe_set_blend_color(struct pipe_context *pipe, 85 const struct pipe_blend_color *blend_color) 86{ 87 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); 88 89 if (!blend_color) 90 return; 91 92 if (memcmp(&llvmpipe->blend_color, blend_color, sizeof *blend_color) == 0) 93 return; 94 95 draw_flush(llvmpipe->draw); 96 97 memcpy(&llvmpipe->blend_color, blend_color, sizeof *blend_color); 98 99 llvmpipe->dirty |= LP_NEW_BLEND_COLOR; 100} 101 102 103/** XXX move someday? Or consolidate all these simple state setters 104 * into one file. 105 */ 106 107 108static void * 109llvmpipe_create_depth_stencil_state(struct pipe_context *pipe, 110 const struct pipe_depth_stencil_alpha_state *depth_stencil) 111{ 112 struct pipe_depth_stencil_alpha_state *state; 113 114 state = mem_dup(depth_stencil, sizeof *depth_stencil); 115 116 if (LP_PERF & PERF_NO_DEPTH) { 117 state->depth_enabled = 0; 118 state->depth_writemask = 0; 119 state->stencil[0].enabled = 0; 120 state->stencil[1].enabled = 0; 121 } 122 123 if (LP_PERF & PERF_NO_ALPHATEST) { 124 state->alpha_enabled = 0; 125 } 126 127 return state; 128} 129 130 131static void 132llvmpipe_bind_depth_stencil_state(struct pipe_context *pipe, 133 void *depth_stencil) 134{ 135 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); 136 137 if (llvmpipe->depth_stencil == depth_stencil) 138 return; 139 140 draw_flush(llvmpipe->draw); 141 142 llvmpipe->depth_stencil = depth_stencil; 143 144 llvmpipe->dirty |= LP_NEW_DEPTH_STENCIL_ALPHA; 145} 146 147 148static void 149llvmpipe_delete_depth_stencil_state(struct pipe_context *pipe, void *depth) 150{ 151 FREE(depth); 152} 153 154 155static void 156llvmpipe_set_stencil_ref(struct pipe_context *pipe, 157 const struct pipe_stencil_ref stencil_ref) 158{ 159 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); 160 161 if (memcmp(&llvmpipe->stencil_ref, &stencil_ref, sizeof stencil_ref) == 0) 162 return; 163 164 draw_flush(llvmpipe->draw); 165 166 memcpy(&llvmpipe->stencil_ref, &stencil_ref, sizeof stencil_ref); 167 168 /* not sure. want new flag? */ 169 llvmpipe->dirty |= LP_NEW_DEPTH_STENCIL_ALPHA; 170} 171 172static void 173llvmpipe_set_sample_mask(struct pipe_context *pipe, 174 unsigned sample_mask) 175{ 176 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); 177 178 if (sample_mask != llvmpipe->sample_mask) { 179 draw_flush(llvmpipe->draw); 180 181 llvmpipe->sample_mask = sample_mask; 182 183 llvmpipe->dirty |= LP_NEW_SAMPLE_MASK; 184 } 185} 186 187static void 188llvmpipe_set_min_samples(struct pipe_context *pipe, 189 unsigned min_samples) 190{ 191 struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); 192 193 if (min_samples != llvmpipe->min_samples) { 194 llvmpipe->min_samples = min_samples; 195 196 llvmpipe->dirty |= LP_NEW_FS; 197 } 198} 199 200void 201llvmpipe_init_blend_funcs(struct llvmpipe_context *llvmpipe) 202{ 203 llvmpipe->pipe.create_blend_state = llvmpipe_create_blend_state; 204 llvmpipe->pipe.bind_blend_state = llvmpipe_bind_blend_state; 205 llvmpipe->pipe.delete_blend_state = llvmpipe_delete_blend_state; 206 207 llvmpipe->pipe.create_depth_stencil_alpha_state = llvmpipe_create_depth_stencil_state; 208 llvmpipe->pipe.bind_depth_stencil_alpha_state = llvmpipe_bind_depth_stencil_state; 209 llvmpipe->pipe.delete_depth_stencil_alpha_state = llvmpipe_delete_depth_stencil_state; 210 211 llvmpipe->pipe.set_blend_color = llvmpipe_set_blend_color; 212 213 llvmpipe->pipe.set_stencil_ref = llvmpipe_set_stencil_ref; 214 llvmpipe->pipe.set_sample_mask = llvmpipe_set_sample_mask; 215 llvmpipe->pipe.set_min_samples = llvmpipe_set_min_samples; 216 217 llvmpipe->dirty |= LP_NEW_SAMPLE_MASK; 218 llvmpipe->sample_mask = ~0; 219} 220