diff options
Diffstat (limited to 'o3d/gpu/command_buffer/service/states_gl.cc')
-rw-r--r-- | o3d/gpu/command_buffer/service/states_gl.cc | 346 |
1 files changed, 346 insertions, 0 deletions
diff --git a/o3d/gpu/command_buffer/service/states_gl.cc b/o3d/gpu/command_buffer/service/states_gl.cc new file mode 100644 index 0000000..2d6fce4 --- /dev/null +++ b/o3d/gpu/command_buffer/service/states_gl.cc @@ -0,0 +1,346 @@ +/* + * Copyright 2009, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +// This file implements the render state-related GAPI functions on GL. + +#include "gpu/command_buffer/service/precompile.h" +#include "gpu/command_buffer/common/o3d_cmd_format.h" +#include "gpu/command_buffer/service/gapi_gl.h" + +namespace command_buffer { +namespace o3d { + +namespace { + +GLenum kGLPolygonModes[] = { + GL_POINT, + GL_LINE, + GL_FILL, +}; +COMPILE_ASSERT(o3d::kNumPolygonMode == arraysize(kGLPolygonModes), + kGLPolygonModes_does_not_match_command_buffer_PolygonMode); + +GLenum kGLComparison[] = { + GL_NEVER, + GL_LESS, + GL_EQUAL, + GL_LEQUAL, + GL_GREATER, + GL_NOTEQUAL, + GL_GEQUAL, + GL_ALWAYS, +}; +COMPILE_ASSERT(o3d::kNumComparison == arraysize(kGLComparison), + kGLComparison_does_not_match_command_buffer_Comparison); + +GLenum kGLBlendFunc[] = { + GL_ZERO, + GL_ONE, + GL_SRC_COLOR, + GL_ONE_MINUS_SRC_COLOR, + GL_SRC_ALPHA, + GL_ONE_MINUS_SRC_ALPHA, + GL_DST_ALPHA, + GL_ONE_MINUS_DST_ALPHA, + GL_DST_COLOR, + GL_ONE_MINUS_DST_COLOR, + GL_SRC_ALPHA_SATURATE, + GL_CONSTANT_COLOR, + GL_ONE_MINUS_CONSTANT_COLOR, +}; +COMPILE_ASSERT(o3d::kNumBlendFunc == arraysize(kGLBlendFunc), + kGLBlendFunc_does_not_match_command_buffer_BlendFunc); + +GLenum kGLBlendEq[] = { + GL_FUNC_ADD, + GL_FUNC_SUBTRACT, + GL_FUNC_REVERSE_SUBTRACT, + GL_MIN, + GL_MAX, +}; +COMPILE_ASSERT(o3d::kNumBlendEq == arraysize(kGLBlendEq), + kGLBlendEq_does_not_match_command_buffer_BlendEq); + +GLenum kGLStencilOp[] = { + GL_KEEP, + GL_ZERO, + GL_REPLACE, + GL_INCR, + GL_DECR, + GL_INVERT, + GL_INCR_WRAP, + GL_DECR_WRAP, +}; +COMPILE_ASSERT(o3d::kNumStencilOp == arraysize(kGLStencilOp), + kGLStencilOp_does_not_match_command_buffer_StencilOp); + +// Check that the definition of the counter-clockwise func/ops match the +// clockwise ones, just shifted by 16 bits, so that we can use +// DecodeStencilFuncOps on both of them. +#define CHECK_CCW_MATCHES_CW(FIELD) \ + COMPILE_ASSERT(o3d::SetStencilTest::CW ## FIELD::kLength == \ + o3d::SetStencilTest::CCW ## FIELD::kLength, \ + CCW ## FIELD ## _length_does_not_match_ ## CW ## FIELD); \ + COMPILE_ASSERT(o3d::SetStencilTest::CW ## FIELD::kShift + 16 == \ + o3d::SetStencilTest::CCW ## FIELD::kShift, \ + CCW ## FIELD ## _shift_does_not_match_ ## CW ## FIELD) + +CHECK_CCW_MATCHES_CW(Func); +CHECK_CCW_MATCHES_CW(PassOp); +CHECK_CCW_MATCHES_CW(FailOp); +CHECK_CCW_MATCHES_CW(ZFailOp); + +#undef CHECK_CCW_MATCHES_CW + +// Decodes stencil test function and operations from the bitfield. +void DecodeStencilFuncOps(Uint32 params, + GLenum *func, + GLenum *pass, + GLenum *fail, + GLenum *zfail) { + // Sanity check. The value has already been tested in + // GAPIDecoder::DecodeSetStencilTest in gapi_decoder.cc. + DCHECK_EQ(o3d::SetStencilTest::Unused1::Get(params), 0); + // Check that the bitmask get cannot generate values outside of the allowed + // range. + COMPILE_ASSERT(o3d::SetStencilTest::CWFunc::kMask < + o3d::kNumComparison, + set_stencil_test_CWFunc_may_produce_invalid_values); + *func = kGLComparison[o3d::SetStencilTest::CWFunc::Get(params)]; + + COMPILE_ASSERT(o3d::SetStencilTest::CWPassOp::kMask < + o3d::kNumStencilOp, + set_stencil_test_CWPassOp_may_produce_invalid_values); + *pass = kGLStencilOp[o3d::SetStencilTest::CWPassOp::Get(params)]; + + COMPILE_ASSERT(o3d::SetStencilTest::CWFailOp::kMask < + o3d::kNumStencilOp, + set_stencil_test_CWFailOp_may_produce_invalid_values); + *fail = kGLStencilOp[o3d::SetStencilTest::CWFailOp::Get(params)]; + + COMPILE_ASSERT(o3d::SetStencilTest::CWZFailOp::kMask < + o3d::kNumStencilOp, + set_stencil_test_CWZFailOp_may_produce_invalid_values); + *zfail = kGLStencilOp[o3d::SetStencilTest::CWZFailOp::Get(params)]; +} + +} // anonymous namespace + +void GAPIGL::SetViewport(unsigned int x, + unsigned int y, + unsigned int width, + unsigned int height, + float z_min, + float z_max) { + glViewport(x, y, width, height); + glDepthRange(z_min, z_max); + // Update the helper constant used for the D3D -> GL remapping. + // See effect_gl.cc for details. + glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, 0, + 1.f / width, 1.f / height, 2.f, 0.f); + CHECK_GL_ERROR(); +} + +void GAPIGL::SetScissor(bool enable, + unsigned int x, + unsigned int y, + unsigned int width, + unsigned int height) { + if (enable) { + glEnable(GL_SCISSOR_TEST); + glScissor(x, y, width, height); + } else { + glDisable(GL_SCISSOR_TEST); + } +} + +void GAPIGL::SetPointLineRaster(bool line_smooth, + bool point_sprite, + float point_size) { + if (line_smooth) { + glEnable(GL_LINE_SMOOTH); + } else { + glDisable(GL_LINE_SMOOTH); + } + if (point_sprite) { + glEnable(GL_POINT_SPRITE); + // TODO: check which TC gets affected by point sprites in D3D. + glActiveTextureARB(GL_TEXTURE0); + glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE); + } else { + glActiveTextureARB(GL_TEXTURE0); + glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_FALSE); + glDisable(GL_POINT_SPRITE); + } + glPointSize(point_size); +} + +void GAPIGL::SetPolygonOffset(float slope_factor, float units) { + glPolygonOffset(slope_factor, units); +} + +void GAPIGL::SetPolygonRaster(o3d::PolygonMode fill_mode, + o3d::FaceCullMode cull_mode) { + DCHECK_LT(fill_mode, kNumPolygonMode); + glPolygonMode(GL_FRONT_AND_BACK, kGLPolygonModes[fill_mode]); + DCHECK_LT(cull_mode, kNumFaceCullMode); + switch (cull_mode) { + case kCullCW: + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + break; + case kCullCCW: + glEnable(GL_CULL_FACE); + glCullFace(GL_FRONT); + break; + default: + glDisable(GL_CULL_FACE); + break; + } +} + +void GAPIGL::SetAlphaTest(bool enable, + float reference, + o3d::Comparison comp) { + DCHECK_LT(comp, kNumComparison); + if (enable) { + glEnable(GL_ALPHA_TEST); + glAlphaFunc(kGLComparison[comp], reference); + } else { + glDisable(GL_ALPHA_TEST); + } +} + +void GAPIGL::SetDepthTest(bool enable, + bool write_enable, + o3d::Comparison comp) { + DCHECK_LT(comp, kNumComparison); + if (enable) { + glEnable(GL_DEPTH_TEST); + glDepthFunc(kGLComparison[comp]); + } else { + glDisable(GL_DEPTH_TEST); + } + glDepthMask(write_enable); +} + +void GAPIGL::SetStencilTest(bool enable, + bool separate_ccw, + unsigned int write_mask, + unsigned int compare_mask, + unsigned int ref, + Uint32 func_ops) { + if (enable) { + glEnable(GL_STENCIL_TEST); + glStencilMask(write_mask); + + GLenum func; + GLenum pass; + GLenum fail; + GLenum zfail; + DecodeStencilFuncOps(func_ops, &func, &pass, &fail, &zfail); + if (separate_ccw) { + glStencilFuncSeparate(GL_FRONT, func, ref, compare_mask); + glStencilOpSeparate(GL_FRONT, pass, fail, zfail); + // Extract upper 16 bits. + Uint32 ccw_func_ops = BitField<16, 16>::Get(func_ops); + GLenum ccw_func; + GLenum ccw_pass; + GLenum ccw_fail; + GLenum ccw_zfail; + DecodeStencilFuncOps(ccw_func_ops, &ccw_func, &ccw_pass, &ccw_fail, + &ccw_zfail); + glStencilFuncSeparate(GL_BACK, ccw_func, ref, compare_mask); + glStencilOpSeparate(GL_BACK, ccw_pass, ccw_fail, ccw_zfail); + } else { + glStencilFunc(func, ref, compare_mask); + glStencilOp(pass, fail, zfail); + } + } else { + glDisable(GL_STENCIL_TEST); + } +} + +void GAPIGL::SetColorWrite(bool red, + bool green, + bool blue, + bool alpha, + bool dither) { + glColorMask(red, green, blue, alpha); + if (dither) { + glEnable(GL_DITHER); + } else { + glDisable(GL_DITHER); + } +} + +void GAPIGL::SetBlending(bool enable, + bool separate_alpha, + BlendEq color_eq, + BlendFunc color_src_func, + BlendFunc color_dst_func, + BlendEq alpha_eq, + BlendFunc alpha_src_func, + BlendFunc alpha_dst_func) { + DCHECK_LT(color_eq, kNumBlendEq); + DCHECK_LT(color_src_func, kNumBlendFunc); + DCHECK_LT(color_dst_func, kNumBlendFunc); + DCHECK_LT(alpha_eq, kNumBlendEq); + DCHECK_LT(alpha_src_func, kNumBlendFunc); + DCHECK_LT(alpha_dst_func, kNumBlendFunc); + if (enable) { + glEnable(GL_BLEND); + GLenum gl_color_eq = kGLBlendEq[color_eq]; + GLenum gl_color_src_func = kGLBlendFunc[color_src_func]; + GLenum gl_color_dst_func = kGLBlendFunc[color_dst_func]; + if (separate_alpha) { + GLenum gl_alpha_eq = kGLBlendEq[alpha_eq]; + GLenum gl_alpha_src_func = kGLBlendFunc[alpha_src_func]; + GLenum gl_alpha_dst_func = kGLBlendFunc[alpha_dst_func]; + glBlendFuncSeparate(gl_color_src_func, gl_color_dst_func, + gl_alpha_src_func, gl_alpha_dst_func); + glBlendEquationSeparate(gl_color_eq, gl_alpha_eq); + } else { + glBlendFunc(gl_color_src_func, gl_color_dst_func); + glBlendEquation(gl_color_eq); + } + } else { + glDisable(GL_BLEND); + } +} + +void GAPIGL::SetBlendingColor(const RGBA &color) { + glBlendColor(color.red, color.green, color.blue, color.alpha); +} + +} // namespace o3d +} // namespace command_buffer |