Ion
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
updatestatetable.cc
Go to the documentation of this file.
1 
19 
20 #include "ion/base/enumhelper.h"
21 #include "ion/base/indexmap.h"
22 #include "ion/base/logging.h"
24 #include "ion/gfx/statetable.h"
25 #include "ion/math/vector.h"
26 
27 namespace ion {
28 namespace gfx {
29 
30 namespace {
31 
33 
38 
39 
42 static void ClearBuffers(const StateTable& st, StateTable* save_state,
43  GraphicsManager* gm) {
44  GLbitfield mask = 0;
45  if (st.IsValueSet(StateTable::kClearColorValue)) {
46  const math::Vector4f& color = st.GetClearColor();
47  if (st.AreSettingsEnforced() || color != save_state->GetClearColor()) {
48  save_state->SetClearColor(color);
49  gm->ClearColor(color[0], color[1], color[2], color[3]);
50  }
51  mask |= GL_COLOR_BUFFER_BIT;
52  }
53  if (st.IsValueSet(StateTable::kClearDepthValue)) {
54  const float value = st.GetClearDepthValue();
55  if (st.AreSettingsEnforced() || value != save_state->GetClearDepthValue()) {
56  save_state->SetClearDepthValue(value);
57  gm->ClearDepthf(value);
58  }
59  mask |= GL_DEPTH_BUFFER_BIT;
60  }
61  if (st.IsValueSet(StateTable::kClearStencilValue)) {
62  const int value = st.GetClearStencilValue();
63  if (st.AreSettingsEnforced() ||
64  value != save_state->GetClearStencilValue()) {
65  save_state->SetClearStencilValue(value);
66  gm->ClearStencil(value);
67  }
68  mask |= GL_STENCIL_BUFFER_BIT;
69  }
70  if (mask)
71  gm->Clear(mask);
72 }
73 
77 static void UpdateAndSetCapability(StateTable::Capability cap,
78  const StateTable& new_state,
79  StateTable* save_state,
80  GraphicsManager* gm) {
82  if (!gm->IsValidStateTableCapability(cap)) {
83  return;
84  }
85  const base::IndexMap<StateTable::Capability, GLenum> capability_map =
86  base::EnumHelper::GetIndexMap<StateTable::Capability>();
87  if (new_state.IsCapabilitySet(cap)) {
88  const bool enabled = new_state.IsEnabled(cap);
89  if (new_state.AreSettingsEnforced() ||
90  enabled != save_state->IsEnabled(cap)) {
91  const GLenum value = capability_map.GetUnorderedIndex(cap);
92  if (enabled)
93  gm->Enable(value);
94  else
95  gm->Disable(value);
96  save_state->Enable(cap, enabled);
97  }
98  }
99 }
100 
104 static void UpdateCapabilities(const StateTable& st0, const StateTable& st1,
105  const StateTable& state_to_test,
106  GraphicsManager* gm) {
107  const base::IndexMap<StateTable::Capability, GLenum> capability_map =
108  base::EnumHelper::GetIndexMap<StateTable::Capability>();
109  const size_t num_capabilities = capability_map.GetCount();
110  for (size_t i = 0; i < num_capabilities; ++i) {
111  const StateTable::Capability st_cap =
112  static_cast<StateTable::Capability>(i);
114  if (!gm->IsValidStateTableCapability(st_cap)) {
115  continue;
116  }
117  if (state_to_test.IsCapabilitySet(st_cap)) {
118  const bool enabled = st1.IsEnabled(st_cap);
119  if (state_to_test.AreSettingsEnforced() ||
120  enabled != st0.IsEnabled(st_cap)) {
121  const GLenum gl_cap = capability_map.GetUnorderedIndex(st_cap);
122  if (enabled)
123  gm->Enable(gl_cap);
124  else
125  gm->Disable(gl_cap);
126  }
127  }
128  }
129 }
130 
135 
136 static void UpdateBlendColor(
137  const StateTable& st0, const StateTable& st1, GraphicsManager* gm) {
138  const math::Vector4f& color = st1.GetBlendColor();
139  if (st1.AreSettingsEnforced() || color != st0.GetBlendColor())
140  gm->BlendColor(color[0], color[1], color[2], color[3]);
141 }
142 
143 static void UpdateBlendEquations(
144  const StateTable& st0, const StateTable& st1, GraphicsManager* gm) {
145  const StateTable::BlendEquation rgb = st1.GetRgbBlendEquation();
146  const StateTable::BlendEquation alpha = st1.GetAlphaBlendEquation();
147  if (st1.AreSettingsEnforced() || rgb != st0.GetRgbBlendEquation() ||
148  alpha != st0.GetAlphaBlendEquation()) {
149  gm->BlendEquationSeparate(base::EnumHelper::GetConstant(rgb),
151  }
152 }
153 
154 static void UpdateBlendFunctions(
155  const StateTable& st0, const StateTable& st1, GraphicsManager* gm) {
157  typedef StateTable::BlendFunctionFactor Factor;
158  const Factor rgb_src = st1.GetRgbBlendFunctionSourceFactor();
159  const Factor rgb_dst = st1.GetRgbBlendFunctionDestinationFactor();
160  const Factor alpha_src = st1.GetAlphaBlendFunctionSourceFactor();
161  const Factor alpha_dst = st1.GetAlphaBlendFunctionDestinationFactor();
162  if (st1.AreSettingsEnforced() ||
163  rgb_src != st0.GetRgbBlendFunctionSourceFactor() ||
164  rgb_dst != st0.GetRgbBlendFunctionDestinationFactor() ||
165  alpha_src != st0.GetAlphaBlendFunctionSourceFactor() ||
166  alpha_dst != st0.GetAlphaBlendFunctionDestinationFactor()) {
167  gm->BlendFuncSeparate(base::EnumHelper::GetConstant(rgb_src),
170  base::EnumHelper::GetConstant(alpha_dst));
171  }
172 }
173 
174 static void UpdateColorWriteMasks(
175  StateTable* st0, const StateTable& st1, GraphicsManager* gm) {
176  const bool red = st1.GetRedColorWriteMask();
177  const bool green = st1.GetGreenColorWriteMask();
178  const bool blue = st1.GetBlueColorWriteMask();
179  const bool alpha = st1.GetAlphaColorWriteMask();
180  if (st1.AreSettingsEnforced() || red != st0->GetRedColorWriteMask() ||
181  green != st0->GetGreenColorWriteMask() ||
182  blue != st0->GetBlueColorWriteMask() ||
183  alpha != st0->GetAlphaColorWriteMask()) {
184  gm->ColorMask(red, green, blue, alpha);
185  st0->SetColorWriteMasks(red, green, blue, alpha);
186  }
187 }
188 
189 static void UpdateCullFaceMode(
190  const StateTable& st0, const StateTable& st1, GraphicsManager* gm) {
191  const StateTable::CullFaceMode mode = st1.GetCullFaceMode();
192  if (st1.AreSettingsEnforced() || mode != st0.GetCullFaceMode())
193  gm->CullFace(base::EnumHelper::GetConstant(mode));
194 }
195 
196 static void UpdateFrontFaceMode(
197  const StateTable& st0, const StateTable& st1, GraphicsManager* gm) {
198  const StateTable::FrontFaceMode mode = st1.GetFrontFaceMode();
199  if (st1.AreSettingsEnforced() || mode != st0.GetFrontFaceMode())
200  gm->FrontFace(base::EnumHelper::GetConstant(mode));
201 }
202 
203 static void UpdateDepthFunction(
204  const StateTable& st0, const StateTable& st1, GraphicsManager* gm) {
205  const StateTable::DepthFunction func = st1.GetDepthFunction();
206  if (st1.AreSettingsEnforced() || func != st0.GetDepthFunction())
207  gm->DepthFunc(base::EnumHelper::GetConstant(func));
208 }
209 
210 static void UpdateDepthRange(
211  const StateTable& st0, const StateTable& st1, GraphicsManager* gm) {
212  const math::Range1f& range = st1.GetDepthRange();
213  if (st1.AreSettingsEnforced() || range != st0.GetDepthRange())
214  gm->DepthRangef(range.GetMinPoint(), range.GetMaxPoint());
215 }
216 
217 static void UpdateDepthWriteMask(
218  StateTable* st0, const StateTable& st1, GraphicsManager* gm) {
219  const bool mask = st1.GetDepthWriteMask();
220  if (st1.AreSettingsEnforced() || mask != st0->GetDepthWriteMask()) {
221  gm->DepthMask(mask);
222  st0->SetDepthWriteMask(mask);
223  }
224 }
225 
226 static void UpdateDrawBuffer(const StateTable& st0, const StateTable& st1,
227  GraphicsManager* gm) {
228  const StateTable::DrawBuffer buf = st1.GetDrawBuffer();
229  if (gm->IsFunctionGroupAvailable(GraphicsManager::kChooseBuffer) &&
230  (st1.AreSettingsEnforced() || buf != st0.GetDrawBuffer())) {
231  gm->DrawBuffer(base::EnumHelper::GetConstant(buf));
232  }
233 }
234 
235 static void UpdateHints(
236  const StateTable& st0, const StateTable& st1, GraphicsManager* gm) {
237  const StateTable::HintMode mipmap_hint =
238  st1.GetHint(StateTable::kGenerateMipmapHint);
239  if (st1.AreSettingsEnforced() ||
240  mipmap_hint != st0.GetHint(StateTable::kGenerateMipmapHint))
241  gm->Hint(GL_GENERATE_MIPMAP_HINT,
242  base::EnumHelper::GetConstant(mipmap_hint));
243 }
244 
245 static void UpdateLineWidth(
246  const StateTable& st0, const StateTable& st1, GraphicsManager* gm) {
247  const float width = st1.GetLineWidth();
248  if (st1.AreSettingsEnforced() || width != st0.GetLineWidth())
249  gm->LineWidth(width);
250 }
251 
252 static void UpdatePolygonOffset(
253  const StateTable& st0, const StateTable& st1, GraphicsManager* gm) {
254  const float factor = st1.GetPolygonOffsetFactor();
255  const float units = st1.GetPolygonOffsetUnits();
256  if (st1.AreSettingsEnforced() || factor != st0.GetPolygonOffsetFactor() ||
257  units != st0.GetPolygonOffsetUnits()) {
258  gm->PolygonOffset(factor, units);
259  }
260 }
261 
262 static void UpdateSampleCoverage(
263  const StateTable& st0, const StateTable& st1, GraphicsManager* gm) {
264  const float value = st1.GetSampleCoverageValue();
265  const bool is_inverted = st1.IsSampleCoverageInverted();
266  if (st1.AreSettingsEnforced() || value != st0.GetSampleCoverageValue() ||
267  is_inverted != st0.IsSampleCoverageInverted()) {
268  gm->SampleCoverage(value, is_inverted);
269  }
270 }
271 
272 static void UpdateScissorBox(
273  StateTable* st0, const StateTable& st1, GraphicsManager* gm) {
274  const math::Range2i& box = st1.GetScissorBox();
275  if (st1.AreSettingsEnforced() || box != st0->GetScissorBox()) {
276  const math::Point2i& min_point = box.GetMinPoint();
277  const math::Vector2i size = box.GetSize();
278  gm->Scissor(min_point[0], min_point[1], size[0], size[1]);
279  st0->SetScissorBox(box);
280  }
281 }
282 
283 static void UpdateStencilFunctions(
284  const StateTable& st0, const StateTable& st1, GraphicsManager* gm) {
285  const StateTable::StencilFunction front_func = st1.GetFrontStencilFunction();
286  const int front_ref = st1.GetFrontStencilReferenceValue();
287  const uint32 front_mask = st1.GetFrontStencilMask();
288  if (st1.AreSettingsEnforced() ||
289  front_func != st0.GetFrontStencilFunction() ||
290  front_ref != st0.GetFrontStencilReferenceValue() ||
291  front_mask != st0.GetFrontStencilMask()) {
292  gm->StencilFuncSeparate(GL_FRONT,
293  base::EnumHelper::GetConstant(front_func),
294  front_ref, front_mask);
295  }
296 
297  const StateTable::StencilFunction back_func = st1.GetBackStencilFunction();
298  const int back_ref = st1.GetBackStencilReferenceValue();
299  const uint32 back_mask = st1.GetBackStencilMask();
300  if (st1.AreSettingsEnforced() || back_func != st0.GetBackStencilFunction() ||
301  back_ref != st0.GetBackStencilReferenceValue() ||
302  back_mask != st0.GetBackStencilMask()) {
303  gm->StencilFuncSeparate(GL_BACK,
305  back_ref, back_mask);
306  }
307 }
308 
309 static void UpdateStencilOperations(
310  const StateTable& st0, const StateTable& st1, GraphicsManager* gm) {
312  typedef StateTable::StencilOperation Op;
313 
314  const Op front_fail = st1.GetFrontStencilFailOperation();
315  const Op front_depth_fail = st1.GetFrontStencilDepthFailOperation();
316  const Op front_pass = st1.GetFrontStencilPassOperation();
317  if (st1.AreSettingsEnforced() ||
318  front_fail != st0.GetFrontStencilFailOperation() ||
319  front_depth_fail != st0.GetFrontStencilDepthFailOperation() ||
320  front_pass != st0.GetFrontStencilPassOperation()) {
321  gm->StencilOpSeparate(GL_FRONT,
322  base::EnumHelper::GetConstant(front_fail),
323  base::EnumHelper::GetConstant(front_depth_fail),
324  base::EnumHelper::GetConstant(front_pass));
325  }
326 
327  const Op back_fail = st1.GetBackStencilFailOperation();
328  const Op back_depth_fail = st1.GetBackStencilDepthFailOperation();
329  const Op back_pass = st1.GetBackStencilPassOperation();
330  if (st1.AreSettingsEnforced() ||
331  back_fail != st0.GetBackStencilFailOperation() ||
332  back_depth_fail != st0.GetBackStencilDepthFailOperation() ||
333  back_pass != st0.GetBackStencilPassOperation()) {
334  gm->StencilOpSeparate(GL_BACK, base::EnumHelper::GetConstant(back_fail),
335  base::EnumHelper::GetConstant(back_depth_fail),
336  base::EnumHelper::GetConstant(back_pass));
337  }
338 }
339 
340 static void UpdateStencilWriteMasks(
341  StateTable* st0, const StateTable& st1, GraphicsManager* gm) {
342  const uint32 front_mask = st1.GetFrontStencilWriteMask();
343  bool do_set = false;
344  if (st1.AreSettingsEnforced() ||
345  front_mask != st0->GetFrontStencilWriteMask()) {
346  gm->StencilMaskSeparate(GL_FRONT, front_mask);
347  do_set = true;
348  }
349 
350  const uint32 back_mask = st1.GetBackStencilWriteMask();
351  if (st1.AreSettingsEnforced() ||
352  back_mask != st0->GetBackStencilWriteMask()) {
353  gm->StencilMaskSeparate(GL_BACK, back_mask);
354  do_set = true;
355  }
356 
357  if (do_set)
358  st0->SetStencilWriteMasks(front_mask, back_mask);
359 }
360 
361 static void UpdateViewport(
362  const StateTable& st0, const StateTable& st1, GraphicsManager* gm) {
363  const math::Range2i& viewport = st1.GetViewport();
364  if (st1.AreSettingsEnforced() || viewport != st0.GetViewport()) {
365  const math::Point2i& min_point = viewport.GetMinPoint();
366  const math::Vector2i size = viewport.GetSize();
367  gm->Viewport(min_point[0], min_point[1], size[0], size[1]);
368  }
369 }
370 
372 
377 
378 
379 static GLint GetInt(GraphicsManager* gm, GLenum what) {
380  GLint i;
381  gm->GetIntegerv(what, &i);
382  return i;
383 }
384 
385 static GLfloat GetFloat(GraphicsManager* gm, GLenum what) {
386  GLfloat f;
387  gm->GetFloatv(what, &f);
388  return f;
389 }
390 
391 static bool GetBool(GraphicsManager* gm, GLenum what) {
392  return GetInt(gm, what) != 0;
393 }
394 
395 template <typename EnumType>
396 static EnumType GetEnum(GraphicsManager* gm, GLenum what) {
397  return base::EnumHelper::GetEnum<EnumType>(GetInt(gm, what));
398 }
399 
400 static const math::Vector4f GetColor(GraphicsManager* gm, GLenum what) {
401  math::Vector4f color;
402  gm->GetFloatv(what, color.Data());
403  return color;
404 }
405 
407 
412 
413 
417 static void CopyCapabilities(GraphicsManager* gm, StateTable* st) {
418  const base::IndexMap<StateTable::Capability, GLenum> capability_map =
419  base::EnumHelper::GetIndexMap<StateTable::Capability>();
420 
421  const size_t num_capabilities = capability_map.GetCount();
422  for (size_t i = 0; i < num_capabilities; ++i) {
423  const StateTable::Capability st_cap =
424  static_cast<StateTable::Capability>(i);
425  if (gm->IsValidStateTableCapability(st_cap)) {
426  const GLenum gl_cap = capability_map.GetUnorderedIndex(st_cap);
427  const bool gl_state = gm->IsEnabled(gl_cap);
428  if (st->IsEnabled(st_cap) != gl_state)
429  st->Enable(st_cap, gl_state);
430  }
431  }
432 }
433 
436 static void CopySetCapabilities(GraphicsManager* gm, StateTable* st) {
437  const base::IndexMap<StateTable::Capability, GLenum> capability_map =
438  base::EnumHelper::GetIndexMap<StateTable::Capability>();
439 
440  const size_t num_capabilities = capability_map.GetCount();
441  for (size_t i = 0; i < num_capabilities; ++i) {
442  const StateTable::Capability st_cap =
443  static_cast<StateTable::Capability>(i);
444  if (st->IsCapabilitySet(st_cap)) {
445  const GLenum gl_cap = capability_map.GetUnorderedIndex(st_cap);
446  if (gm->IsValidStateTableCapability(st_cap)) {
447  const bool gl_state = gm->IsEnabled(gl_cap);
448  if (st->IsEnabled(st_cap) != gl_state)
449  st->Enable(st_cap, gl_state);
450  }
451  }
452  }
453 }
454 
456 #define ION_GET_ENUM(st_type, gl_enum) GetEnum<StateTable::st_type>(gm, gl_enum)
457 
459 static void CopyValues(GraphicsManager* gm, StateTable* st) {
460  st->SetBlendColor(GetColor(gm, GL_BLEND_COLOR));
461  st->SetBlendEquations(ION_GET_ENUM(BlendEquation, GL_BLEND_EQUATION_RGB),
462  ION_GET_ENUM(BlendEquation, GL_BLEND_EQUATION_ALPHA));
463  st->SetBlendFunctions(ION_GET_ENUM(BlendFunctionFactor, GL_BLEND_SRC_RGB),
464  ION_GET_ENUM(BlendFunctionFactor, GL_BLEND_DST_RGB),
465  ION_GET_ENUM(BlendFunctionFactor, GL_BLEND_SRC_ALPHA),
466  ION_GET_ENUM(BlendFunctionFactor, GL_BLEND_DST_ALPHA));
467  st->SetClearColor(GetColor(gm, GL_COLOR_CLEAR_VALUE));
468  {
469  GLint mask[4];
470  gm->GetIntegerv(GL_COLOR_WRITEMASK, mask);
471  st->SetColorWriteMasks(mask[0], mask[1], mask[2], mask[3]);
472  }
473  st->SetCullFaceMode(ION_GET_ENUM(CullFaceMode, GL_CULL_FACE_MODE));
474  st->SetFrontFaceMode(ION_GET_ENUM(FrontFaceMode, GL_FRONT_FACE));
475  st->SetClearDepthValue(GetFloat(gm, GL_DEPTH_CLEAR_VALUE));
476  st->SetDepthFunction(ION_GET_ENUM(DepthFunction, GL_DEPTH_FUNC));
477  {
478  GLfloat range[2];
479  gm->GetFloatv(GL_DEPTH_RANGE, range);
480  st->SetDepthRange(math::Range1f(range[0], range[1]));
481  }
482  st->SetDepthWriteMask(GetBool(gm, GL_DEPTH_WRITEMASK));
483  if (gm->IsFunctionGroupAvailable(GraphicsManager::kChooseBuffer))
484  st->SetDrawBuffer(ION_GET_ENUM(DrawBuffer, GL_DRAW_BUFFER));
487  st->SetLineWidth(GetFloat(gm, GL_LINE_WIDTH));
488  st->SetPolygonOffset(GetFloat(gm, GL_POLYGON_OFFSET_FACTOR),
489  GetFloat(gm, GL_POLYGON_OFFSET_UNITS));
490  st->SetSampleCoverage(GetFloat(gm, GL_SAMPLE_COVERAGE_VALUE),
491  GetBool(gm, GL_SAMPLE_COVERAGE_INVERT));
492  {
493  GLint box[4];
494  gm->GetIntegerv(GL_SCISSOR_BOX, box);
495  st->SetScissorBox(
496  math::Range2i::BuildWithSize(math::Point2i(box[0], box[1]),
497  math::Vector2i(box[2], box[3])));
498  }
499  st->SetStencilFunctions(ION_GET_ENUM(StencilFunction, GL_STENCIL_FUNC),
500  GetInt(gm, GL_STENCIL_REF),
501  GetInt(gm, GL_STENCIL_VALUE_MASK),
502  ION_GET_ENUM(StencilFunction, GL_STENCIL_BACK_FUNC),
503  GetInt(gm, GL_STENCIL_BACK_REF),
504  GetInt(gm, GL_STENCIL_BACK_VALUE_MASK));
505  st->SetStencilOperations(
506  ION_GET_ENUM(StencilOperation, GL_STENCIL_FAIL),
507  ION_GET_ENUM(StencilOperation, GL_STENCIL_PASS_DEPTH_FAIL),
508  ION_GET_ENUM(StencilOperation, GL_STENCIL_PASS_DEPTH_PASS),
509  ION_GET_ENUM(StencilOperation, GL_STENCIL_BACK_FAIL),
510  ION_GET_ENUM(StencilOperation, GL_STENCIL_BACK_PASS_DEPTH_FAIL),
511  ION_GET_ENUM(StencilOperation, GL_STENCIL_BACK_PASS_DEPTH_PASS));
512  st->SetClearStencilValue(GetInt(gm, GL_STENCIL_CLEAR_VALUE));
513  st->SetStencilWriteMasks(GetInt(gm, GL_STENCIL_WRITEMASK),
514  GetInt(gm, GL_STENCIL_BACK_WRITEMASK));
515  {
516  GLint viewport[4];
517  gm->GetIntegerv(GL_VIEWPORT, viewport);
518  st->SetViewport(
519  math::Range2i::BuildWithSize(math::Point2i(viewport[0], viewport[1]),
520  math::Vector2i(viewport[2], viewport[3])));
521  }
522 }
523 
526 static void CopySetValues(GraphicsManager* gm, StateTable* st) {
527  if (st->IsValueSet(StateTable::kBlendColorValue))
528  st->SetBlendColor(GetColor(gm, GL_BLEND_COLOR));
529  if (st->IsValueSet(StateTable::kBlendEquationsValue))
530  st->SetBlendEquations(ION_GET_ENUM(BlendEquation, GL_BLEND_EQUATION_RGB),
531  ION_GET_ENUM(BlendEquation, GL_BLEND_EQUATION_ALPHA));
532  if (st->IsValueSet(StateTable::kBlendFunctionsValue))
533  st->SetBlendFunctions(
534  ION_GET_ENUM(BlendFunctionFactor, GL_BLEND_SRC_RGB),
535  ION_GET_ENUM(BlendFunctionFactor, GL_BLEND_DST_RGB),
536  ION_GET_ENUM(BlendFunctionFactor, GL_BLEND_SRC_ALPHA),
537  ION_GET_ENUM(BlendFunctionFactor, GL_BLEND_DST_ALPHA));
538  if (st->IsValueSet(StateTable::kClearColorValue))
539  st->SetClearColor(GetColor(gm, GL_COLOR_CLEAR_VALUE));
540  if (st->IsValueSet(StateTable::kColorWriteMasksValue)) {
541  GLint mask[4];
542  gm->GetIntegerv(GL_COLOR_WRITEMASK, mask);
543  st->SetColorWriteMasks(mask[0], mask[1], mask[2], mask[3]);
544  }
545  if (st->IsValueSet(StateTable::kCullFaceModeValue))
546  st->SetCullFaceMode(ION_GET_ENUM(CullFaceMode, GL_CULL_FACE_MODE));
547  if (st->IsValueSet(StateTable::kFrontFaceModeValue))
548  st->SetFrontFaceMode(ION_GET_ENUM(FrontFaceMode, GL_FRONT_FACE));
549  if (st->IsValueSet(StateTable::kClearDepthValue))
550  st->SetClearDepthValue(GetFloat(gm, GL_DEPTH_CLEAR_VALUE));
551  if (st->IsValueSet(StateTable::kDepthFunctionValue))
552  st->SetDepthFunction(ION_GET_ENUM(DepthFunction, GL_DEPTH_FUNC));
553  if (st->IsValueSet(StateTable::kDepthRangeValue)) {
554  GLfloat range[2];
555  gm->GetFloatv(GL_DEPTH_RANGE, range);
556  st->SetDepthRange(math::Range1f(range[0], range[1]));
557  }
558  if (st->IsValueSet(StateTable::kDepthWriteMaskValue))
559  st->SetDepthWriteMask(GetBool(gm, GL_DEPTH_WRITEMASK));
560  if (st->IsValueSet(StateTable::kDrawBufferValue) &&
561  gm->IsFunctionGroupAvailable(GraphicsManager::kChooseBuffer))
562  st->SetDrawBuffer(ION_GET_ENUM(DrawBuffer, GL_DRAW_BUFFER));
563  if (st->IsValueSet(StateTable::kLineWidthValue))
564  st->SetLineWidth(GetFloat(gm, GL_LINE_WIDTH));
565  if (st->IsValueSet(StateTable::kPolygonOffsetValue))
566  st->SetPolygonOffset(GetFloat(gm, GL_POLYGON_OFFSET_FACTOR),
567  GetFloat(gm, GL_POLYGON_OFFSET_UNITS));
568  if (st->IsValueSet(StateTable::kSampleCoverageValue))
569  st->SetSampleCoverage(GetFloat(gm, GL_SAMPLE_COVERAGE_VALUE),
570  GetBool(gm, GL_SAMPLE_COVERAGE_INVERT));
571  if (st->IsValueSet(StateTable::kScissorBoxValue)) {
572  GLint box[4];
573  gm->GetIntegerv(GL_SCISSOR_BOX, box);
574  st->SetScissorBox(math::Range2i::BuildWithSize(
575  math::Point2i(box[0], box[1]), math::Vector2i(box[2], box[3])));
576  }
577  if (st->IsValueSet(StateTable::kStencilFunctionsValue))
578  st->SetStencilFunctions(ION_GET_ENUM(StencilFunction, GL_STENCIL_FUNC),
579  GetInt(gm, GL_STENCIL_REF),
580  GetInt(gm, GL_STENCIL_VALUE_MASK),
581  ION_GET_ENUM(StencilFunction, GL_STENCIL_BACK_FUNC),
582  GetInt(gm, GL_STENCIL_BACK_REF),
583  GetInt(gm, GL_STENCIL_BACK_VALUE_MASK));
584  if (st->IsValueSet(StateTable::kStencilOperationsValue))
585  st->SetStencilOperations(
586  ION_GET_ENUM(StencilOperation, GL_STENCIL_FAIL),
587  ION_GET_ENUM(StencilOperation, GL_STENCIL_PASS_DEPTH_FAIL),
588  ION_GET_ENUM(StencilOperation, GL_STENCIL_PASS_DEPTH_PASS),
589  ION_GET_ENUM(StencilOperation, GL_STENCIL_BACK_FAIL),
590  ION_GET_ENUM(StencilOperation, GL_STENCIL_BACK_PASS_DEPTH_FAIL),
591  ION_GET_ENUM(StencilOperation, GL_STENCIL_BACK_PASS_DEPTH_PASS));
592  if (st->IsValueSet(StateTable::kClearStencilValue))
593  st->SetClearStencilValue(GetInt(gm, GL_STENCIL_CLEAR_VALUE));
594  if (st->IsValueSet(StateTable::kStencilWriteMasksValue))
595  st->SetStencilWriteMasks(GetInt(gm, GL_STENCIL_WRITEMASK),
596  GetInt(gm, GL_STENCIL_BACK_WRITEMASK));
597  if (st->IsValueSet(StateTable::kViewportValue)) {
598  GLint viewport[4];
599  gm->GetIntegerv(GL_VIEWPORT, viewport);
600  st->SetViewport(
601  math::Range2i::BuildWithSize(math::Point2i(viewport[0], viewport[1]),
602  math::Vector2i(viewport[2], viewport[3])));
603  }
604 }
605 #undef ION_GET_ENUM
606 
608 static void ResetValues(const StateTable& default_st, StateTable* st) {
609 #define ION_IS_SAME(func) st->func == default_st.func
610 #define ION_RESET(condition, value_enum) \
611  if (condition) \
612  st->ResetValue(StateTable::value_enum)
613 #define ION_RESET1(value_enum, func) \
614  ION_RESET(ION_IS_SAME(func), value_enum)
615 #define ION_RESET2(value_enum, func1, func2) \
616  ION_RESET(ION_IS_SAME(func1) && ION_IS_SAME(func2), value_enum)
617 #define ION_RESET4(value_enum, func1, func2, func3, func4) \
618  ION_RESET(ION_IS_SAME(func1) && ION_IS_SAME(func2) && \
619  ION_IS_SAME(func3) && ION_IS_SAME(func4), value_enum)
620 #define ION_RESET6(value_enum, func1, func2, func3, func4, func5, func6) \
621  ION_RESET(ION_IS_SAME(func1) && ION_IS_SAME(func2) && \
622  ION_IS_SAME(func3) && ION_IS_SAME(func4) && \
623  ION_IS_SAME(func5) && ION_IS_SAME(func6), value_enum)
624 
625  ION_RESET1(kBlendColorValue, GetBlendColor());
626  ION_RESET2(kBlendEquationsValue,
627  GetRgbBlendEquation(), GetAlphaBlendEquation());
628  ION_RESET4(kBlendFunctionsValue,
629  GetRgbBlendFunctionSourceFactor(),
630  GetAlphaBlendFunctionSourceFactor(),
631  GetRgbBlendFunctionDestinationFactor(),
632  GetAlphaBlendFunctionDestinationFactor());
633  ION_RESET1(kClearColorValue, GetClearColor());
634  ION_RESET4(kColorWriteMasksValue,
635  GetRedColorWriteMask(), GetBlueColorWriteMask(),
636  GetGreenColorWriteMask(), GetAlphaColorWriteMask());
637  ION_RESET1(kCullFaceModeValue, GetCullFaceMode());
638  ION_RESET1(kFrontFaceModeValue, GetFrontFaceMode());
639  ION_RESET1(kFrontFaceModeValue, GetFrontFaceMode());
640  ION_RESET1(kClearDepthValue, GetClearDepthValue());
641  ION_RESET1(kDepthFunctionValue, GetDepthFunction());
642  ION_RESET1(kDepthRangeValue, GetDepthRange());
643  ION_RESET1(kDepthWriteMaskValue, GetDepthWriteMask());
644  ION_RESET1(kDrawBufferValue, GetDrawBuffer());
645  ION_RESET1(kHintsValue, GetHint(StateTable::kGenerateMipmapHint));
646  ION_RESET1(kLineWidthValue, GetLineWidth());
647  ION_RESET2(kPolygonOffsetValue,
648  GetPolygonOffsetFactor(), GetPolygonOffsetUnits());
649  ION_RESET2(kSampleCoverageValue,
650  GetSampleCoverageValue(), IsSampleCoverageInverted());
651  ION_RESET1(kScissorBoxValue, GetScissorBox());
652  ION_RESET6(kStencilFunctionsValue,
653  GetFrontStencilFunction(), GetBackStencilFunction(),
654  GetFrontStencilReferenceValue(), GetBackStencilReferenceValue(),
655  GetFrontStencilMask(), GetBackStencilMask());
656  ION_RESET6(kStencilOperationsValue,
657  GetFrontStencilFailOperation(), GetBackStencilFailOperation(),
658  GetFrontStencilDepthFailOperation(),
659  GetBackStencilDepthFailOperation(),
660  GetFrontStencilPassOperation(), GetBackStencilPassOperation());
661  ION_RESET1(kClearStencilValue, GetClearStencilValue());
662  ION_RESET2(kStencilWriteMasksValue,
663  GetFrontStencilWriteMask(), GetBackStencilWriteMask());
664  ION_RESET1(kViewportValue, GetViewport());
665 
666 #undef ION_RESET4
667 #undef ION_RESET2
668 #undef ION_RESET1
669 #undef ION_RESET
670 #undef ION_IS_SAME
671 }
672 
673 } // anonymous namespace
674 
676 
681 
682 
683 void UpdateStateTable(int default_width, int default_height,
684  GraphicsManager* gm, StateTable* st) {
685  DCHECK(gm);
686  DCHECK(st);
687 
689  st->Reset();
690 
693  CopyCapabilities(gm, st);
694  CopyValues(gm, st);
695 
699  StateTable(default_width, default_height));
700  ResetValues(*default_st, st);
701 }
702 
703 #define ION_UPDATE_CLEAR_VALUE(enum_name, update_func) \
704  if (new_state.IsValueSet(StateTable::enum_name)) \
705  update_func(save_state, new_state, gm)
706 #define ION_UPDATE_CLEAR_ONLY_VALUE(enum_name, clear_enum_name, update_func) \
707  if (new_state.IsValueSet(StateTable::enum_name) && \
708  new_state.IsValueSet(StateTable::clear_enum_name)) \
709  update_func(save_state, new_state, gm)
710 #define ION_UPDATE_VALUE(enum_name, update_func) \
711  if (new_state.IsValueSet(StateTable::enum_name)) \
712  update_func(*save_state, new_state, gm)
713 
714 void ClearFromStateTable(const StateTable& new_state,
715  StateTable* save_state,
716  GraphicsManager* gm) {
717  UpdateAndSetCapability(StateTable::kDither, new_state, save_state, gm);
718  UpdateAndSetCapability(StateTable::kScissorTest, new_state, save_state, gm);
719  if (new_state.GetSetValueCount()) {
722  ION_UPDATE_CLEAR_VALUE(kScissorBoxValue, UpdateScissorBox);
726  ION_UPDATE_CLEAR_ONLY_VALUE(kColorWriteMasksValue, kClearColorValue,
727  UpdateColorWriteMasks);
728  ION_UPDATE_CLEAR_ONLY_VALUE(kDepthWriteMaskValue, kClearDepthValue,
729  UpdateDepthWriteMask);
730  ION_UPDATE_CLEAR_ONLY_VALUE(kStencilWriteMasksValue, kClearStencilValue,
731  UpdateStencilWriteMasks);
732  ClearBuffers(new_state, save_state, gm);
733  }
734 }
735 
737  DCHECK(gm);
738  DCHECK(st);
739 
740  CopySetCapabilities(gm, st);
741  CopySetValues(gm, st);
742 }
743 
744 void UpdateFromStateTable(const StateTable& new_state,
745  StateTable* save_state,
746  GraphicsManager* gm) {
747  DCHECK(gm);
748 
751  if (new_state.GetSetCapabilityCount() &&
752  (new_state.AreSettingsEnforced() ||
753  !StateTable::AreCapabilitiesSame(*save_state, new_state)))
754  UpdateCapabilities(*save_state, new_state, new_state, gm);
755 
757  if (new_state.GetSetValueCount()) {
758  ION_UPDATE_VALUE(kBlendColorValue, UpdateBlendColor);
759  ION_UPDATE_VALUE(kBlendEquationsValue, UpdateBlendEquations);
760  ION_UPDATE_VALUE(kBlendFunctionsValue, UpdateBlendFunctions);
761  ION_UPDATE_CLEAR_VALUE(kColorWriteMasksValue, UpdateColorWriteMasks);
762  ION_UPDATE_VALUE(kCullFaceModeValue, UpdateCullFaceMode);
763  ION_UPDATE_VALUE(kDepthFunctionValue, UpdateDepthFunction);
764  ION_UPDATE_VALUE(kDepthRangeValue, UpdateDepthRange);
765  ION_UPDATE_CLEAR_VALUE(kDepthWriteMaskValue, UpdateDepthWriteMask);
766  ION_UPDATE_VALUE(kDrawBufferValue, UpdateDrawBuffer);
767  ION_UPDATE_VALUE(kFrontFaceModeValue, UpdateFrontFaceMode);
768  ION_UPDATE_VALUE(kHintsValue, UpdateHints);
769  ION_UPDATE_VALUE(kLineWidthValue, UpdateLineWidth);
770  ION_UPDATE_VALUE(kPolygonOffsetValue, UpdatePolygonOffset);
771  ION_UPDATE_VALUE(kSampleCoverageValue, UpdateSampleCoverage);
772  ION_UPDATE_CLEAR_VALUE(kScissorBoxValue, UpdateScissorBox);
773  ION_UPDATE_VALUE(kStencilFunctionsValue, UpdateStencilFunctions);
774  ION_UPDATE_VALUE(kStencilOperationsValue, UpdateStencilOperations);
775  ION_UPDATE_CLEAR_VALUE(kStencilWriteMasksValue, UpdateStencilWriteMasks);
776  ION_UPDATE_VALUE(kViewportValue, UpdateViewport);
777  }
778 }
779 
780 #undef ION_UPDATE_CLEAR_VALUE
781 #undef ION_UPDATE_CLEAR_ONLY_VALUE
782 #undef ION_UPDATE_VALUE
783 
784 } // namespace gfx
785 } // namespace ion
void UpdateSettingsInStateTable(StateTable *st, GraphicsManager *gm)
This internal function can be used to update a StateTable instance to match the current OpenGL settin...
GraphicsManager manages the graphics library for an application.
kShortTerm is used for objects that are very transient in nature, such as scratch memory used to comp...
Definition: allocator.h:36
static uint32 GetConstant(EnumType e)
Returns the constant value corresponding to an enum.
Definition: enumhelper.h:80
#define ION_RESET2(value_enum, func1, func2)
void ClearFromStateTable(const StateTable &new_state, StateTable *save_state, GraphicsManager *gm)
This internal function can be used to update the Clear()-related OpenGL state (dithering, scissor test, write masks, scissor box, and clear values) managed by a GraphicsManager to match a StateTable, and updates save_state to contain the new state.
StencilFunction
OpenGL stencil functions.
Definition: statetable.h:187
FrontFaceMode
OpenGL front face modes.
Definition: statetable.h:169
CullFaceMode
OpenGL cull face modes.
Definition: statetable.h:136
size_t GetSetCapabilityCount() const
Returns the number of capabilities that are set in the instance.
Definition: statetable.h:310
#define DCHECK(expr)
Definition: logging.h:331
double value
HintMode
OpenGL hint modes.
Definition: statetable.h:175
Capability
Enumerated types for StateTable items.
Definition: statetable.h:55
Range< 2, int32 > Range2i
Definition: range.h:371
#define GL_GENERATE_MIPMAP_HINT
Definition: glheaders.h:402
DepthFunction
OpenGL depth test functions.
Definition: statetable.h:143
#define ION_UPDATE_CLEAR_ONLY_VALUE(enum_name, clear_enum_name, update_func)
static bool AreCapabilitiesSame(const StateTable &st0, const StateTable &st1)
Returns true if the capabilities set in two instances are the same.
Definition: statetable.h:315
const AllocatorPtr & GetAllocatorForLifetime(AllocationLifetime lifetime) const
Convenience function that returns the Allocator to use to allocate an object with a specific lifetime...
Definition: allocatable.h:78
#define ION_UPDATE_CLEAR_VALUE(enum_name, update_func)
void UpdateStateTable(int default_width, int default_height, GraphicsManager *gm, StateTable *st)
Public functions.
DrawBuffer
OpenGL draw buffers.
Definition: statetable.h:155
BlendFunctionFactor
OpenGL blend function factors.
Definition: statetable.h:110
void Reset()
Resets all items to their default values.
Definition: statetable.cc:32
Copyright 2016 Google Inc.
int width
BlendEquation
Other enumerated types.
Definition: statetable.h:103
void UpdateFromStateTable(const StateTable &new_state, StateTable *save_state, GraphicsManager *gm)
This internal function can be used to update the OpenGL state managed by a GraphicsManager to match a...
#define ION_UPDATE_VALUE(enum_name, update_func)
#define ION_RESET1(value_enum, func)
bool AreSettingsEnforced() const
Definition: statetable.h:350
StencilOperation
OpenGL stencil operations.
Definition: statetable.h:199
size_t GetSetValueCount() const
Returns the number of values that are set in the instance.
Definition: statetable.h:337
A StateTable represents a collection of graphical state items that affect OpenGL rendering.
Definition: statetable.h:48
#define ION_RESET4(value_enum, func1, func2, func3, func4)
A SharedPtr is a smart shared pointer to an instance of some class that implements reference counting...
Definition: sharedptr.h:60
#define ION_RESET6(value_enum, func1, func2, func3, func4, func5, func6)
Range< 1, float > Range1f
Definition: range.h:365
#define ION_GET_ENUM(st_type, gl_enum)
For brevity and clarity in the below functions.