//
// Copyright 2016 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Context9:
//   D3D9-specific functionality associated with a GL Context.
//

#include "libANGLE/renderer/d3d/d3d9/Context9.h"

#include "common/string_utils.h"
#include "libANGLE/renderer/OverlayImpl.h"
#include "libANGLE/renderer/d3d/CompilerD3D.h"
#include "libANGLE/renderer/d3d/ProgramD3D.h"
#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
#include "libANGLE/renderer/d3d/SamplerD3D.h"
#include "libANGLE/renderer/d3d/ShaderD3D.h"
#include "libANGLE/renderer/d3d/TextureD3D.h"
#include "libANGLE/renderer/d3d/d3d9/Buffer9.h"
#include "libANGLE/renderer/d3d/d3d9/Fence9.h"
#include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h"
#include "libANGLE/renderer/d3d/d3d9/Query9.h"
#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
#include "libANGLE/renderer/d3d/d3d9/StateManager9.h"
#include "libANGLE/renderer/d3d/d3d9/VertexArray9.h"

namespace rx
{

Context9::Context9(const gl::State &state, gl::ErrorSet *errorSet, Renderer9 *renderer)
    : ContextD3D(state, errorSet), mRenderer(renderer)
{}

Context9::~Context9() {}

angle::Result Context9::initialize()
{
    return angle::Result::Continue;
}

void Context9::onDestroy(const gl::Context *context)
{
    mIncompleteTextures.onDestroy(context);
}

CompilerImpl *Context9::createCompiler()
{
    return new CompilerD3D(SH_HLSL_3_0_OUTPUT);
}

ShaderImpl *Context9::createShader(const gl::ShaderState &data)
{
    return new ShaderD3D(data, mRenderer->getFeatures(), mRenderer->getNativeExtensions());
}

ProgramImpl *Context9::createProgram(const gl::ProgramState &data)
{
    return new ProgramD3D(data, mRenderer);
}

FramebufferImpl *Context9::createFramebuffer(const gl::FramebufferState &data)
{
    return new Framebuffer9(data, mRenderer);
}

TextureImpl *Context9::createTexture(const gl::TextureState &state)
{
    switch (state.getType())
    {
        case gl::TextureType::_2D:
            return new TextureD3D_2D(state, mRenderer);
        case gl::TextureType::CubeMap:
            return new TextureD3D_Cube(state, mRenderer);
        case gl::TextureType::External:
            return new TextureD3D_External(state, mRenderer);
        default:
            UNREACHABLE();
    }
    return nullptr;
}

RenderbufferImpl *Context9::createRenderbuffer(const gl::RenderbufferState &state)
{
    return new RenderbufferD3D(state, mRenderer);
}

BufferImpl *Context9::createBuffer(const gl::BufferState &state)
{
    return new Buffer9(state, mRenderer);
}

VertexArrayImpl *Context9::createVertexArray(const gl::VertexArrayState &data)
{
    return new VertexArray9(data);
}

QueryImpl *Context9::createQuery(gl::QueryType type)
{
    return new Query9(mRenderer, type);
}

FenceNVImpl *Context9::createFenceNV()
{
    return new FenceNV9(mRenderer);
}

SyncImpl *Context9::createSync()
{
    // D3D9 doesn't support ES 3.0 and its sync objects.
    UNREACHABLE();
    return nullptr;
}

TransformFeedbackImpl *Context9::createTransformFeedback(const gl::TransformFeedbackState &state)
{
    UNREACHABLE();
    return nullptr;
}

SamplerImpl *Context9::createSampler(const gl::SamplerState &state)
{
    return new SamplerD3D(state);
}

ProgramPipelineImpl *Context9::createProgramPipeline(const gl::ProgramPipelineState &data)
{
    UNREACHABLE();
    return nullptr;
}

std::vector<PathImpl *> Context9::createPaths(GLsizei)
{
    return std::vector<PathImpl *>();
}

MemoryObjectImpl *Context9::createMemoryObject()
{
    UNREACHABLE();
    return nullptr;
}

SemaphoreImpl *Context9::createSemaphore()
{
    UNREACHABLE();
    return nullptr;
}

OverlayImpl *Context9::createOverlay(const gl::OverlayState &state)
{
    // Not implemented.
    return new OverlayImpl(state);
}

angle::Result Context9::flush(const gl::Context *context)
{
    return mRenderer->flush(context);
}

angle::Result Context9::finish(const gl::Context *context)
{
    return mRenderer->finish(context);
}

angle::Result Context9::drawArrays(const gl::Context *context,
                                   gl::PrimitiveMode mode,
                                   GLint first,
                                   GLsizei count)
{
    return mRenderer->genericDrawArrays(context, mode, first, count, 0);
}

angle::Result Context9::drawArraysInstanced(const gl::Context *context,
                                            gl::PrimitiveMode mode,
                                            GLint first,
                                            GLsizei count,
                                            GLsizei instanceCount)
{
    return mRenderer->genericDrawArrays(context, mode, first, count, instanceCount);
}

angle::Result Context9::drawArraysInstancedBaseInstance(const gl::Context *context,
                                                        gl::PrimitiveMode mode,
                                                        GLint first,
                                                        GLsizei count,
                                                        GLsizei instanceCount,
                                                        GLuint baseInstance)
{
    ANGLE_HR_UNREACHABLE(this);
    return angle::Result::Continue;
}

angle::Result Context9::drawElements(const gl::Context *context,
                                     gl::PrimitiveMode mode,
                                     GLsizei count,
                                     gl::DrawElementsType type,
                                     const void *indices)
{
    return mRenderer->genericDrawElements(context, mode, count, type, indices, 0);
}

angle::Result Context9::drawElementsBaseVertex(const gl::Context *context,
                                               gl::PrimitiveMode mode,
                                               GLsizei count,
                                               gl::DrawElementsType type,
                                               const void *indices,
                                               GLint baseVertex)
{
    ANGLE_HR_UNREACHABLE(this);
    return angle::Result::Continue;
}

angle::Result Context9::drawElementsInstanced(const gl::Context *context,
                                              gl::PrimitiveMode mode,
                                              GLsizei count,
                                              gl::DrawElementsType type,
                                              const void *indices,
                                              GLsizei instances)
{
    return mRenderer->genericDrawElements(context, mode, count, type, indices, instances);
}

angle::Result Context9::drawElementsInstancedBaseVertex(const gl::Context *context,
                                                        gl::PrimitiveMode mode,
                                                        GLsizei count,
                                                        gl::DrawElementsType type,
                                                        const void *indices,
                                                        GLsizei instances,
                                                        GLint baseVertex)
{
    ANGLE_HR_UNREACHABLE(this);
    return angle::Result::Continue;
}

angle::Result Context9::drawElementsInstancedBaseVertexBaseInstance(const gl::Context *context,
                                                                    gl::PrimitiveMode mode,
                                                                    GLsizei count,
                                                                    gl::DrawElementsType type,
                                                                    const void *indices,
                                                                    GLsizei instances,
                                                                    GLint baseVertex,
                                                                    GLuint baseInstance)
{
    ANGLE_HR_UNREACHABLE(this);
    return angle::Result::Continue;
}

angle::Result Context9::drawRangeElements(const gl::Context *context,
                                          gl::PrimitiveMode mode,
                                          GLuint start,
                                          GLuint end,
                                          GLsizei count,
                                          gl::DrawElementsType type,
                                          const void *indices)
{
    return mRenderer->genericDrawElements(context, mode, count, type, indices, 0);
}

angle::Result Context9::drawRangeElementsBaseVertex(const gl::Context *context,
                                                    gl::PrimitiveMode mode,
                                                    GLuint start,
                                                    GLuint end,
                                                    GLsizei count,
                                                    gl::DrawElementsType type,
                                                    const void *indices,
                                                    GLint baseVertex)
{
    ANGLE_HR_UNREACHABLE(this);
    return angle::Result::Continue;
}

angle::Result Context9::drawArraysIndirect(const gl::Context *context,
                                           gl::PrimitiveMode mode,
                                           const void *indirect)
{
    ANGLE_HR_UNREACHABLE(this);
    return angle::Result::Stop;
}

angle::Result Context9::drawElementsIndirect(const gl::Context *context,
                                             gl::PrimitiveMode mode,
                                             gl::DrawElementsType type,
                                             const void *indirect)
{
    ANGLE_HR_UNREACHABLE(this);
    return angle::Result::Stop;
}

gl::GraphicsResetStatus Context9::getResetStatus()
{
    return mRenderer->getResetStatus();
}

std::string Context9::getVendorString() const
{
    return mRenderer->getVendorString();
}

std::string Context9::getRendererDescription() const
{
    return mRenderer->getRendererDescription();
}

void Context9::insertEventMarker(GLsizei length, const char *marker)
{
    mRenderer->getAnnotator()->setMarker(marker);
}

void Context9::pushGroupMarker(GLsizei length, const char *marker)
{
    mRenderer->getAnnotator()->beginEvent(marker, marker);
    mMarkerStack.push(std::string(marker));
}

void Context9::popGroupMarker()
{
    const char *marker = nullptr;
    if (!mMarkerStack.empty())
    {
        marker = mMarkerStack.top().c_str();
        mMarkerStack.pop();
        mRenderer->getAnnotator()->endEvent(marker);
    }
}

void Context9::pushDebugGroup(GLenum source, GLuint id, const std::string &message)
{
    // Fall through to the EXT_debug_marker functions
    pushGroupMarker(static_cast<GLsizei>(message.size()), message.c_str());
}

void Context9::popDebugGroup()
{
    // Fall through to the EXT_debug_marker functions
    popGroupMarker();
}

angle::Result Context9::syncState(const gl::Context *context,
                                  const gl::State::DirtyBits &dirtyBits,
                                  const gl::State::DirtyBits &bitMask)
{
    mRenderer->getStateManager()->syncState(mState, dirtyBits);
    return angle::Result::Continue;
}

GLint Context9::getGPUDisjoint()
{
    return mRenderer->getGPUDisjoint();
}

GLint64 Context9::getTimestamp()
{
    return mRenderer->getTimestamp();
}

angle::Result Context9::onMakeCurrent(const gl::Context *context)
{
    mRenderer->getStateManager()->setAllDirtyBits();
    return mRenderer->ensureVertexDataManagerInitialized(context);
}

gl::Caps Context9::getNativeCaps() const
{
    return mRenderer->getNativeCaps();
}

const gl::TextureCapsMap &Context9::getNativeTextureCaps() const
{
    return mRenderer->getNativeTextureCaps();
}

const gl::Extensions &Context9::getNativeExtensions() const
{
    return mRenderer->getNativeExtensions();
}

const gl::Limitations &Context9::getNativeLimitations() const
{
    return mRenderer->getNativeLimitations();
}

angle::Result Context9::dispatchCompute(const gl::Context *context,
                                        GLuint numGroupsX,
                                        GLuint numGroupsY,
                                        GLuint numGroupsZ)
{
    ANGLE_HR_UNREACHABLE(this);
    return angle::Result::Stop;
}

angle::Result Context9::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect)
{
    ANGLE_HR_UNREACHABLE(this);
    return angle::Result::Stop;
}

angle::Result Context9::memoryBarrier(const gl::Context *context, GLbitfield barriers)
{
    ANGLE_HR_UNREACHABLE(this);
    return angle::Result::Stop;
}

angle::Result Context9::memoryBarrierByRegion(const gl::Context *context, GLbitfield barriers)
{
    ANGLE_HR_UNREACHABLE(this);
    return angle::Result::Stop;
}

angle::Result Context9::getIncompleteTexture(const gl::Context *context,
                                             gl::TextureType type,
                                             gl::Texture **textureOut)
{
    return mIncompleteTextures.getIncompleteTexture(context, type, nullptr, textureOut);
}

void Context9::handleResult(HRESULT hr,
                            const char *message,
                            const char *file,
                            const char *function,
                            unsigned int line)
{
    ASSERT(FAILED(hr));

    if (d3d9::isDeviceLostError(hr))
    {
        mRenderer->notifyDeviceLost();
    }

    GLenum glErrorCode = DefaultGLErrorCode(hr);

    std::stringstream errorStream;
    errorStream << "Internal D3D9 error: " << gl::FmtHR(hr) << ": " << message;

    mErrors->handleError(glErrorCode, errorStream.str().c_str(), file, function, line);
}
}  // namespace rx
