// Copyright 2017 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "dawn/native/opengl/SamplerGL.h"

#include "dawn/common/Assert.h"
#include "dawn/native/opengl/DeviceGL.h"
#include "dawn/native/opengl/UtilsGL.h"

namespace dawn::native::opengl {

namespace {
GLenum MagFilterMode(wgpu::FilterMode filter) {
    switch (filter) {
        case wgpu::FilterMode::Nearest:
            return GL_NEAREST;
        case wgpu::FilterMode::Linear:
            return GL_LINEAR;
    }
    UNREACHABLE();
}

GLenum MinFilterMode(wgpu::FilterMode minFilter, wgpu::FilterMode mipMapFilter) {
    switch (minFilter) {
        case wgpu::FilterMode::Nearest:
            switch (mipMapFilter) {
                case wgpu::FilterMode::Nearest:
                    return GL_NEAREST_MIPMAP_NEAREST;
                case wgpu::FilterMode::Linear:
                    return GL_NEAREST_MIPMAP_LINEAR;
            }
        case wgpu::FilterMode::Linear:
            switch (mipMapFilter) {
                case wgpu::FilterMode::Nearest:
                    return GL_LINEAR_MIPMAP_NEAREST;
                case wgpu::FilterMode::Linear:
                    return GL_LINEAR_MIPMAP_LINEAR;
            }
    }
    UNREACHABLE();
}

GLenum WrapMode(wgpu::AddressMode mode) {
    switch (mode) {
        case wgpu::AddressMode::Repeat:
            return GL_REPEAT;
        case wgpu::AddressMode::MirrorRepeat:
            return GL_MIRRORED_REPEAT;
        case wgpu::AddressMode::ClampToEdge:
            return GL_CLAMP_TO_EDGE;
    }
    UNREACHABLE();
}

}  // namespace

Sampler::Sampler(Device* device, const SamplerDescriptor* descriptor)
    : SamplerBase(device, descriptor) {
    const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;

    gl.GenSamplers(1, &mFilteringHandle);
    SetupGLSampler(mFilteringHandle, descriptor, false);

    gl.GenSamplers(1, &mNonFilteringHandle);
    SetupGLSampler(mNonFilteringHandle, descriptor, true);
}

Sampler::~Sampler() = default;

void Sampler::DestroyImpl() {
    SamplerBase::DestroyImpl();
    const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
    gl.DeleteSamplers(1, &mFilteringHandle);
    gl.DeleteSamplers(1, &mNonFilteringHandle);
}

void Sampler::SetupGLSampler(GLuint sampler,
                             const SamplerDescriptor* descriptor,
                             bool forceNearest) {
    Device* device = ToBackend(GetDevice());
    const OpenGLFunctions& gl = device->gl;

    if (forceNearest) {
        gl.SamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        gl.SamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
    } else {
        gl.SamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, MagFilterMode(descriptor->magFilter));
        gl.SamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER,
                             MinFilterMode(descriptor->minFilter, descriptor->mipmapFilter));
    }
    gl.SamplerParameteri(sampler, GL_TEXTURE_WRAP_R, WrapMode(descriptor->addressModeW));
    gl.SamplerParameteri(sampler, GL_TEXTURE_WRAP_S, WrapMode(descriptor->addressModeU));
    gl.SamplerParameteri(sampler, GL_TEXTURE_WRAP_T, WrapMode(descriptor->addressModeV));

    gl.SamplerParameterf(sampler, GL_TEXTURE_MIN_LOD, descriptor->lodMinClamp);
    gl.SamplerParameterf(sampler, GL_TEXTURE_MAX_LOD, descriptor->lodMaxClamp);

    if (descriptor->compare != wgpu::CompareFunction::Undefined) {
        gl.SamplerParameteri(sampler, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
        gl.SamplerParameteri(sampler, GL_TEXTURE_COMPARE_FUNC,
                             ToOpenGLCompareFunction(descriptor->compare));
    }

    if (gl.IsAtLeastGL(4, 6) || gl.IsGLExtensionSupported("GL_EXT_texture_filter_anisotropic")) {
        gl.SamplerParameterf(sampler, GL_TEXTURE_MAX_ANISOTROPY, GetMaxAnisotropy());
    }
}

GLuint Sampler::GetFilteringHandle() const {
    return mFilteringHandle;
}

GLuint Sampler::GetNonFilteringHandle() const {
    return mNonFilteringHandle;
}

}  // namespace dawn::native::opengl
