use crate::gles3::gles3_bindings;
use crate::gles3::gles3_bindings::types::GLenum;
use crate::{
RafxAddressMode, RafxBlendFactor, RafxBlendOp, RafxBlendState, RafxColorFlags, RafxCompareOp,
RafxCullMode, RafxDepthState, RafxFilterType, RafxFrontFace, RafxMemoryUsage,
RafxPrimitiveTopology, RafxRasterizerState, RafxResult, RafxStencilOp,
};
impl RafxFilterType {
pub fn gles3_filter_type(self) -> GLenum {
match self {
RafxFilterType::Nearest => gles3_bindings::NEAREST,
RafxFilterType::Linear => gles3_bindings::LINEAR,
}
}
}
impl RafxAddressMode {
pub fn gles3_address_mode(self) -> Option<GLenum> {
match self {
RafxAddressMode::Mirror => Some(gles3_bindings::MIRRORED_REPEAT),
RafxAddressMode::Repeat => Some(gles3_bindings::REPEAT),
RafxAddressMode::ClampToEdge => Some(gles3_bindings::CLAMP_TO_EDGE),
RafxAddressMode::ClampToBorder => None,
}
}
}
impl RafxPrimitiveTopology {
pub fn gles3_topology(self) -> Option<GLenum> {
match self {
RafxPrimitiveTopology::PointList => Some(gles3_bindings::POINTS),
RafxPrimitiveTopology::LineList => Some(gles3_bindings::LINES),
RafxPrimitiveTopology::LineStrip => Some(gles3_bindings::LINE_STRIP),
RafxPrimitiveTopology::TriangleList => Some(gles3_bindings::TRIANGLES),
RafxPrimitiveTopology::TriangleStrip => Some(gles3_bindings::TRIANGLE_STRIP),
RafxPrimitiveTopology::PatchList => None,
}
}
}
impl RafxMemoryUsage {
pub fn gles3_usage(self) -> Option<GLenum> {
match self {
RafxMemoryUsage::Unknown => None,
RafxMemoryUsage::GpuOnly => Some(gles3_bindings::STATIC_DRAW),
RafxMemoryUsage::CpuOnly => Some(gles3_bindings::NONE),
RafxMemoryUsage::CpuToGpu => Some(gles3_bindings::DYNAMIC_DRAW),
RafxMemoryUsage::GpuToCpu => Some(gles3_bindings::STREAM_DRAW),
}
}
}
impl RafxCullMode {
pub fn gles3_cull_mode(self) -> GLenum {
match self {
RafxCullMode::None => gles3_bindings::NONE,
RafxCullMode::Back => gles3_bindings::BACK,
RafxCullMode::Front => gles3_bindings::FRONT,
}
}
}
impl RafxFrontFace {
pub fn gles3_front_face(
self,
reversed: bool,
) -> GLenum {
if reversed {
match self {
RafxFrontFace::CounterClockwise => gles3_bindings::CW,
RafxFrontFace::Clockwise => gles3_bindings::CCW,
}
} else {
match self {
RafxFrontFace::CounterClockwise => gles3_bindings::CCW,
RafxFrontFace::Clockwise => gles3_bindings::CW,
}
}
}
}
impl RafxCompareOp {
pub fn gles3_compare_op(self) -> GLenum {
match self {
RafxCompareOp::Never => gles3_bindings::NEVER,
RafxCompareOp::Less => gles3_bindings::LESS,
RafxCompareOp::Equal => gles3_bindings::EQUAL,
RafxCompareOp::LessOrEqual => gles3_bindings::LEQUAL,
RafxCompareOp::Greater => gles3_bindings::GREATER,
RafxCompareOp::NotEqual => gles3_bindings::NOTEQUAL,
RafxCompareOp::GreaterOrEqual => gles3_bindings::GEQUAL,
RafxCompareOp::Always => gles3_bindings::ALWAYS,
}
}
}
impl RafxStencilOp {
pub fn gles3_stencil_op(self) -> GLenum {
match self {
RafxStencilOp::Keep => gles3_bindings::KEEP,
RafxStencilOp::Zero => gles3_bindings::ZERO,
RafxStencilOp::Replace => gles3_bindings::REPLACE,
RafxStencilOp::IncrementAndClamp => gles3_bindings::INCR,
RafxStencilOp::DecrementAndClamp => gles3_bindings::DECR,
RafxStencilOp::Invert => gles3_bindings::INVERT,
RafxStencilOp::IncrementAndWrap => gles3_bindings::INCR_WRAP,
RafxStencilOp::DecrementAndWrap => gles3_bindings::INCR_WRAP,
}
}
}
#[derive(Debug)]
pub struct Gles3RasterizerState {
pub cull_mode: GLenum,
pub front_face: GLenum,
pub scissor_test: bool,
}
impl From<&RafxRasterizerState> for Gles3RasterizerState {
fn from(state: &RafxRasterizerState) -> Self {
Gles3RasterizerState {
cull_mode: state.cull_mode.gles3_cull_mode(),
front_face: state.front_face.gles3_front_face(false),
scissor_test: state.scissor,
}
}
}
#[derive(Debug)]
pub struct Gles3DepthStencilState {
pub depth_test_enable: bool,
pub depth_write_enable: bool,
pub depth_compare_op: GLenum,
pub stencil_test_enable: bool,
pub stencil_write_mask: u8,
pub front_depth_fail_op: GLenum,
pub front_stencil_compare_op: GLenum,
pub front_stencil_fail_op: GLenum,
pub front_stencil_pass_op: GLenum,
pub back_depth_fail_op: GLenum,
pub back_stencil_compare_op: GLenum,
pub back_stencil_fail_op: GLenum,
pub back_stencil_pass_op: GLenum,
}
impl From<&RafxDepthState> for Gles3DepthStencilState {
fn from(state: &RafxDepthState) -> Self {
Gles3DepthStencilState {
depth_test_enable: state.depth_test_enable,
depth_write_enable: state.depth_write_enable,
depth_compare_op: state.depth_compare_op.gles3_compare_op(),
stencil_test_enable: state.stencil_test_enable,
stencil_write_mask: state.stencil_write_mask,
front_depth_fail_op: state.front_depth_fail_op.gles3_stencil_op(),
front_stencil_compare_op: state.front_stencil_compare_op.gles3_compare_op(),
front_stencil_fail_op: state.front_stencil_fail_op.gles3_stencil_op(),
front_stencil_pass_op: state.front_stencil_pass_op.gles3_stencil_op(),
back_depth_fail_op: state.back_depth_fail_op.gles3_stencil_op(),
back_stencil_compare_op: state.back_stencil_compare_op.gles3_compare_op(),
back_stencil_fail_op: state.back_stencil_fail_op.gles3_stencil_op(),
back_stencil_pass_op: state.back_stencil_pass_op.gles3_stencil_op(),
}
}
}
impl RafxBlendFactor {
pub fn gles3_blend_factor(self) -> GLenum {
match self {
RafxBlendFactor::Zero => gles3_bindings::ZERO,
RafxBlendFactor::One => gles3_bindings::ONE,
RafxBlendFactor::SrcColor => gles3_bindings::SRC_COLOR,
RafxBlendFactor::OneMinusSrcColor => gles3_bindings::ONE_MINUS_SRC_COLOR,
RafxBlendFactor::DstColor => gles3_bindings::DST_COLOR,
RafxBlendFactor::OneMinusDstColor => gles3_bindings::ONE_MINUS_DST_COLOR,
RafxBlendFactor::SrcAlpha => gles3_bindings::SRC_ALPHA,
RafxBlendFactor::OneMinusSrcAlpha => gles3_bindings::ONE_MINUS_SRC_ALPHA,
RafxBlendFactor::DstAlpha => gles3_bindings::DST_ALPHA,
RafxBlendFactor::OneMinusDstAlpha => gles3_bindings::ONE_MINUS_DST_ALPHA,
RafxBlendFactor::SrcAlphaSaturate => gles3_bindings::SRC_ALPHA_SATURATE,
RafxBlendFactor::ConstantColor => gles3_bindings::CONSTANT_COLOR,
RafxBlendFactor::OneMinusConstantColor => gles3_bindings::ONE_MINUS_CONSTANT_COLOR,
}
}
}
impl RafxBlendOp {
pub fn gles3_blend_op(self) -> Option<GLenum> {
match self {
RafxBlendOp::Add => Some(gles3_bindings::FUNC_ADD),
RafxBlendOp::Subtract => Some(gles3_bindings::FUNC_SUBTRACT),
RafxBlendOp::ReverseSubtract => Some(gles3_bindings::FUNC_REVERSE_SUBTRACT),
RafxBlendOp::Min => None,
RafxBlendOp::Max => None,
}
}
}
#[derive(Debug)]
pub struct Gles3BlendState {
pub enabled: bool,
pub src_factor: GLenum,
pub dst_factor: GLenum,
pub src_factor_alpha: GLenum,
pub dst_factor_alpha: GLenum,
pub blend_op: GLenum,
pub blend_op_alpha: GLenum,
pub color_flags: RafxColorFlags,
}
impl RafxBlendState {
pub fn gles3_blend_state(&self) -> RafxResult<Gles3BlendState> {
if self.independent_blend {
unimplemented!("GL ES 2.0 does not support independent blend states");
}
let rt_state = self
.render_target_blend_states
.get(0)
.ok_or("RafxBlendState has no render target blend states")?;
let blend_state = Gles3BlendState {
enabled: rt_state.blend_enabled(),
src_factor: rt_state.src_factor.gles3_blend_factor(),
dst_factor: rt_state.dst_factor.gles3_blend_factor(),
src_factor_alpha: rt_state.src_factor_alpha.gles3_blend_factor(),
dst_factor_alpha: rt_state.dst_factor_alpha.gles3_blend_factor(),
blend_op: rt_state.blend_op.gles3_blend_op().ok_or_else(|| {
format!(
"GL ES 2.0 does not support blend op {:?}",
rt_state.blend_op
)
})?,
blend_op_alpha: rt_state.blend_op.gles3_blend_op().ok_or_else(|| {
format!(
"GL ES 2.0 does not support blend op {:?}",
rt_state.blend_op
)
})?,
color_flags: rt_state.masks,
};
Ok(blend_state)
}
}
pub const GL_CUBE_MAP_TARGETS: [GLenum; 6] = [
gles3_bindings::TEXTURE_CUBE_MAP_POSITIVE_X,
gles3_bindings::TEXTURE_CUBE_MAP_NEGATIVE_X,
gles3_bindings::TEXTURE_CUBE_MAP_POSITIVE_Y,
gles3_bindings::TEXTURE_CUBE_MAP_NEGATIVE_Y,
gles3_bindings::TEXTURE_CUBE_MAP_POSITIVE_Z,
gles3_bindings::TEXTURE_CUBE_MAP_NEGATIVE_Z,
];
pub fn array_layer_to_cube_map_target(array_layer: u16) -> GLenum {
if array_layer > 5 {
unimplemented!("GL ES 2.0 does not support more than 6 images for a cubemap")
}
GL_CUBE_MAP_TARGETS[array_layer as usize]
}