<commit_before>//
// Copyright 2015 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.
//

// TextureGL.cpp: Implements the class methods for TextureGL.

#include "libANGLE/renderer/gl/TextureGL.h"

#include "common/debug.h"
#include "common/utilities.h"
#include "libANGLE/State.h"
#include "libANGLE/angletypes.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/gl/BufferGL.h"
#include "libANGLE/renderer/gl/FunctionsGL.h"
#include "libANGLE/renderer/gl/StateManagerGL.h"

namespace rx
{

static void SetUnpackStateForTexImage(StateManagerGL *stateManager, const gl::PixelUnpackState &unpack)
{
    const gl::Buffer *unpackBuffer = unpack.pixelBuffer.get();
    if (unpackBuffer != nullptr)
    {
        UNIMPLEMENTED();
    }
    if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 || unpack.skipImages != 0)
    {
        UNIMPLEMENTED();
    }
    stateManager->setPixelUnpackState(unpack.alignment, unpack.rowLength);
}

static bool UseTexImage2D(GLenum textureType)
{
    return textureType == GL_TEXTURE_2D || textureType == GL_TEXTURE_CUBE_MAP;
}

static bool UseTexImage3D(GLenum textureType)
{
    return textureType == GL_TEXTURE_2D_ARRAY || textureType == GL_TEXTURE_3D;
}

static bool CompatibleTextureTarget(GLenum textureType, GLenum textureTarget)
{
    if (textureType != GL_TEXTURE_CUBE_MAP)
    {
        return textureType == textureTarget;
    }
    else
    {
        return gl::IsCubeMapTextureTarget(textureType);
    }
}

TextureGL::TextureGL(GLenum type, const FunctionsGL *functions, StateManagerGL *stateManager)
    : TextureImpl(),
      mTextureType(type),
      mFunctions(functions),
      mStateManager(stateManager),
      mAppliedSamplerState(),
      mTextureID(0)
{
    ASSERT(mFunctions);
    ASSERT(mStateManager);

    mFunctions->genTextures(1, &mTextureID);
}

TextureGL::~TextureGL()
{
    if (mTextureID)
    {
        mFunctions->deleteTextures(1, &mTextureID);
        mTextureID = 0;
    }
}

void TextureGL::setUsage(GLenum usage)
{
    // GL_ANGLE_texture_usage not implemented for desktop GL
    UNREACHABLE();
}

gl::Error TextureGL::setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type,
                              const gl::PixelUnpackState &unpack, const uint8_t *pixels)
{
    (void)&CompatibleTextureTarget; // Reference this function to avoid warnings.
    ASSERT(CompatibleTextureTarget(mTextureType, target));

    SetUnpackStateForTexImage(mStateManager, unpack);

    mStateManager->bindTexture(mTextureType, mTextureID);
    if (UseTexImage2D(mTextureType))
    {
        ASSERT(size.depth == 1);
        mFunctions->texImage2D(target, level, internalFormat, size.width, size.height, 0, format, type, pixels);
    }
    else if (UseTexImage3D(mTextureType))
    {
        mFunctions->texImage3D(target, level, internalFormat, size.width, size.height, size.depth, 0, format, type, pixels);
    }
    else
    {
        UNREACHABLE();
    }

    return gl::Error(GL_NO_ERROR);
}

gl::Error TextureGL::setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type,
                                 const gl::PixelUnpackState &unpack, const uint8_t *pixels)
{
    ASSERT(CompatibleTextureTarget(mTextureType, target));

    SetUnpackStateForTexImage(mStateManager, unpack);

    mStateManager->bindTexture(mTextureType, mTextureID);
    if (UseTexImage2D(mTextureType))
    {
        ASSERT(area.z == 0 && area.depth == 1);
        mFunctions->texSubImage2D(target, level, area.x, area.y, area.width, area.height, format, type, pixels);
    }
    else if (UseTexImage3D(mTextureType))
    {
        mFunctions->texSubImage3D(target, level, area.x, area.y, area.z, area.width, area.height, area.depth,
                                  format, type, pixels);
    }
    else
    {
        UNREACHABLE();
    }

    return gl::Error(GL_NO_ERROR);
}

gl::Error TextureGL::setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size,
                                        const gl::PixelUnpackState &unpack, const uint8_t *pixels)
{
    ASSERT(CompatibleTextureTarget(mTextureType, target));

    SetUnpackStateForTexImage(mStateManager, unpack);

    const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
    size_t depthPitch = internalFormatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, size.width, size.height,
                                                             unpack.alignment, unpack.rowLength);
    size_t dataSize = internalFormatInfo.computeBlockSize(GL_UNSIGNED_BYTE, size.width, size.height) * depthPitch;

    mStateManager->bindTexture(mTextureType, mTextureID);
    if (UseTexImage2D(mTextureType))
    {
        ASSERT(size.depth == 1);
        mFunctions->compressedTexImage2D(target, level, internalFormat, size.width, size.height, 0, dataSize, pixels);
    }
    else if (UseTexImage3D(mTextureType))
    {
        mFunctions->compressedTexImage3D(target, level, internalFormat, size.width, size.height, size.depth, 0,
                                         dataSize, pixels);
    }
    else
    {
        UNREACHABLE();
    }

    return gl::Error(GL_NO_ERROR);
}

gl::Error TextureGL::setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format,
                                           const gl::PixelUnpackState &unpack, const uint8_t *pixels)
{
    ASSERT(CompatibleTextureTarget(mTextureType, target));

    SetUnpackStateForTexImage(mStateManager, unpack);

    const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(format);
    size_t depthPitch = internalFormatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height,
                                                             unpack.alignment, unpack.rowLength);
    size_t dataSize = internalFormatInfo.computeBlockSize(GL_UNSIGNED_BYTE, area.width, area.height) * depthPitch;

    mStateManager->bindTexture(mTextureType, mTextureID);
    if (UseTexImage2D(mTextureType))
    {
        ASSERT(area.z == 0 && area.depth == 1);
        mFunctions->compressedTexSubImage2D(target, level, area.x, area.y, area.width, area.height, format, dataSize,
                                            pixels);
    }
    else if (UseTexImage3D(mTextureType))
    {
        mFunctions->compressedTexSubImage3D(target, level, area.x, area.y, area.z, area.width, area.height, area.depth,
                                            format, dataSize, pixels);
    }
    else
    {
        UNREACHABLE();
    }

    return gl::Error(GL_NO_ERROR);
}

gl::Error TextureGL::copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat,
                               const gl::Framebuffer *source)
{
    UNIMPLEMENTED();
    return gl::Error(GL_INVALID_OPERATION);
}

gl::Error TextureGL::copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea,
                                  const gl::Framebuffer *source)
{
    UNIMPLEMENTED();
    return gl::Error(GL_INVALID_OPERATION);
}

gl::Error TextureGL::setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size)
{
    // TODO: emulate texture storage with TexImage calls if on GL version <4.2 or the
    // ARB_texture_storage extension is not available.

    mStateManager->bindTexture(mTextureType, mTextureID);
    if (UseTexImage2D(mTextureType))
    {
        ASSERT(size.depth == 1);
        mFunctions->texStorage2D(target, levels, internalFormat, size.width, size.height);
    }
    else if (UseTexImage3D(mTextureType))
    {
        mFunctions->texStorage3D(target, levels, internalFormat, size.width, size.height, size.depth);
    }
    else
    {
        UNREACHABLE();
    }

    return gl::Error(GL_NO_ERROR);
}

gl::Error TextureGL::generateMipmaps()
{
    mStateManager->bindTexture(mTextureType, mTextureID);
    mFunctions->generateMipmap(mTextureType);
    return gl::Error(GL_NO_ERROR);
}

void TextureGL::bindTexImage(egl::Surface *surface)
{
    UNIMPLEMENTED();
}

void TextureGL::releaseTexImage()
{
    UNIMPLEMENTED();
}

template <typename T>
static inline void SyncSamplerStateMember(const FunctionsGL *functions, const gl::SamplerState &newState,
                                          gl::SamplerState &curState, GLenum textureType, GLenum name,
                                          T(gl::SamplerState::*samplerMember))
{
    if (curState.*samplerMember != newState.*samplerMember)
    {
        curState.*samplerMember = newState.*samplerMember;
        functions->texParameterf(textureType, name, curState.*samplerMember);
    }
}

void TextureGL::syncSamplerState(const gl::SamplerState &samplerState) const
{
    if (mAppliedSamplerState != samplerState)
    {
        mStateManager->bindTexture(mTextureType, mTextureID);
        SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_MIN_FILTER, &gl::SamplerState::minFilter);
        SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_MAG_FILTER, &gl::SamplerState::magFilter);
        SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_WRAP_S, &gl::SamplerState::wrapS);
        SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_WRAP_T, &gl::SamplerState::wrapT);
        SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_WRAP_R, &gl::SamplerState::wrapR);
        SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_MAX_ANISOTROPY_EXT, &gl::SamplerState::maxAnisotropy);
        SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_BASE_LEVEL, &gl::SamplerState::baseLevel);
        SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_MAX_LEVEL, &gl::SamplerState::maxLevel);
        SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_MIN_LOD, &gl::SamplerState::minLod);
        SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_MAX_LOD, &gl::SamplerState::maxLod);
        SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_COMPARE_MODE, &gl::SamplerState::compareMode);
        SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_COMPARE_FUNC, &gl::SamplerState::compareFunc);
        SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_SWIZZLE_R, &gl::SamplerState::swizzleRed);
        SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_SWIZZLE_G, &gl::SamplerState::swizzleGreen);
        SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_SWIZZLE_B, &gl::SamplerState::swizzleBlue);
        SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_SWIZZLE_A, &gl::SamplerState::swizzleAlpha);
    }
}

GLuint TextureGL::getTextureID() const
{
    return mTextureID;
}

}
<commit_msg>Fix incorrect assertion.<commit_after>//
// Copyright 2015 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.
//

// TextureGL.cpp: Implements the class methods for TextureGL.

#include "libANGLE/renderer/gl/TextureGL.h"

#include "common/debug.h"
#include "common/utilities.h"
#include "libANGLE/State.h"
#include "libANGLE/angletypes.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/gl/BufferGL.h"
#include "libANGLE/renderer/gl/FunctionsGL.h"
#include "libANGLE/renderer/gl/StateManagerGL.h"

namespace rx
{

static void SetUnpackStateForTexImage(StateManagerGL *stateManager, const gl::PixelUnpackState &unpack)
{
    const gl::Buffer *unpackBuffer = unpack.pixelBuffer.get();
    if (unpackBuffer != nullptr)
    {
        UNIMPLEMENTED();
    }
    if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 || unpack.skipImages != 0)
    {
        UNIMPLEMENTED();
    }
    stateManager->setPixelUnpackState(unpack.alignment, unpack.rowLength);
}

static bool UseTexImage2D(GLenum textureType)
{
    return textureType == GL_TEXTURE_2D || textureType == GL_TEXTURE_CUBE_MAP;
}

static bool UseTexImage3D(GLenum textureType)
{
    return textureType == GL_TEXTURE_2D_ARRAY || textureType == GL_TEXTURE_3D;
}

static bool CompatibleTextureTarget(GLenum textureType, GLenum textureTarget)
{
    if (textureType != GL_TEXTURE_CUBE_MAP)
    {
        return textureType == textureTarget;
    }
    else
    {
        return gl::IsCubeMapTextureTarget(textureTarget);
    }
}

TextureGL::TextureGL(GLenum type, const FunctionsGL *functions, StateManagerGL *stateManager)
    : TextureImpl(),
      mTextureType(type),
      mFunctions(functions),
      mStateManager(stateManager),
      mAppliedSamplerState(),
      mTextureID(0)
{
    ASSERT(mFunctions);
    ASSERT(mStateManager);

    mFunctions->genTextures(1, &mTextureID);
}

TextureGL::~TextureGL()
{
    if (mTextureID)
    {
        mFunctions->deleteTextures(1, &mTextureID);
        mTextureID = 0;
    }
}

void TextureGL::setUsage(GLenum usage)
{
    // GL_ANGLE_texture_usage not implemented for desktop GL
    UNREACHABLE();
}

gl::Error TextureGL::setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type,
                              const gl::PixelUnpackState &unpack, const uint8_t *pixels)
{
    UNUSED_ASSERTION_VARIABLE(&CompatibleTextureTarget); // Reference this function to avoid warnings.
    ASSERT(CompatibleTextureTarget(mTextureType, target));

    SetUnpackStateForTexImage(mStateManager, unpack);

    mStateManager->bindTexture(mTextureType, mTextureID);
    if (UseTexImage2D(mTextureType))
    {
        ASSERT(size.depth == 1);
        mFunctions->texImage2D(target, level, internalFormat, size.width, size.height, 0, format, type, pixels);
    }
    else if (UseTexImage3D(mTextureType))
    {
        mFunctions->texImage3D(target, level, internalFormat, size.width, size.height, size.depth, 0, format, type, pixels);
    }
    else
    {
        UNREACHABLE();
    }

    return gl::Error(GL_NO_ERROR);
}

gl::Error TextureGL::setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type,
                                 const gl::PixelUnpackState &unpack, const uint8_t *pixels)
{
    ASSERT(CompatibleTextureTarget(mTextureType, target));

    SetUnpackStateForTexImage(mStateManager, unpack);

    mStateManager->bindTexture(mTextureType, mTextureID);
    if (UseTexImage2D(mTextureType))
    {
        ASSERT(area.z == 0 && area.depth == 1);
        mFunctions->texSubImage2D(target, level, area.x, area.y, area.width, area.height, format, type, pixels);
    }
    else if (UseTexImage3D(mTextureType))
    {
        mFunctions->texSubImage3D(target, level, area.x, area.y, area.z, area.width, area.height, area.depth,
                                  format, type, pixels);
    }
    else
    {
        UNREACHABLE();
    }

    return gl::Error(GL_NO_ERROR);
}

gl::Error TextureGL::setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size,
                                        const gl::PixelUnpackState &unpack, const uint8_t *pixels)
{
    ASSERT(CompatibleTextureTarget(mTextureType, target));

    SetUnpackStateForTexImage(mStateManager, unpack);

    const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
    size_t depthPitch = internalFormatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, size.width, size.height,
                                                             unpack.alignment, unpack.rowLength);
    size_t dataSize = internalFormatInfo.computeBlockSize(GL_UNSIGNED_BYTE, size.width, size.height) * depthPitch;

    mStateManager->bindTexture(mTextureType, mTextureID);
    if (UseTexImage2D(mTextureType))
    {
        ASSERT(size.depth == 1);
        mFunctions->compressedTexImage2D(target, level, internalFormat, size.width, size.height, 0, dataSize, pixels);
    }
    else if (UseTexImage3D(mTextureType))
    {
        mFunctions->compressedTexImage3D(target, level, internalFormat, size.width, size.height, size.depth, 0,
                                         dataSize, pixels);
    }
    else
    {
        UNREACHABLE();
    }

    return gl::Error(GL_NO_ERROR);
}

gl::Error TextureGL::setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format,
                                           const gl::PixelUnpackState &unpack, const uint8_t *pixels)
{
    ASSERT(CompatibleTextureTarget(mTextureType, target));

    SetUnpackStateForTexImage(mStateManager, unpack);

    const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(format);
    size_t depthPitch = internalFormatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height,
                                                             unpack.alignment, unpack.rowLength);
    size_t dataSize = internalFormatInfo.computeBlockSize(GL_UNSIGNED_BYTE, area.width, area.height) * depthPitch;

    mStateManager->bindTexture(mTextureType, mTextureID);
    if (UseTexImage2D(mTextureType))
    {
        ASSERT(area.z == 0 && area.depth == 1);
        mFunctions->compressedTexSubImage2D(target, level, area.x, area.y, area.width, area.height, format, dataSize,
                                            pixels);
    }
    else if (UseTexImage3D(mTextureType))
    {
        mFunctions->compressedTexSubImage3D(target, level, area.x, area.y, area.z, area.width, area.height, area.depth,
                                            format, dataSize, pixels);
    }
    else
    {
        UNREACHABLE();
    }

    return gl::Error(GL_NO_ERROR);
}

gl::Error TextureGL::copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat,
                               const gl::Framebuffer *source)
{
    UNIMPLEMENTED();
    return gl::Error(GL_INVALID_OPERATION);
}

gl::Error TextureGL::copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea,
                                  const gl::Framebuffer *source)
{
    UNIMPLEMENTED();
    return gl::Error(GL_INVALID_OPERATION);
}

gl::Error TextureGL::setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size)
{
    // TODO: emulate texture storage with TexImage calls if on GL version <4.2 or the
    // ARB_texture_storage extension is not available.

    mStateManager->bindTexture(mTextureType, mTextureID);
    if (UseTexImage2D(mTextureType))
    {
        ASSERT(size.depth == 1);
        mFunctions->texStorage2D(target, levels, internalFormat, size.width, size.height);
    }
    else if (UseTexImage3D(mTextureType))
    {
        mFunctions->texStorage3D(target, levels, internalFormat, size.width, size.height, size.depth);
    }
    else
    {
        UNREACHABLE();
    }

    return gl::Error(GL_NO_ERROR);
}

gl::Error TextureGL::generateMipmaps()
{
    mStateManager->bindTexture(mTextureType, mTextureID);
    mFunctions->generateMipmap(mTextureType);
    return gl::Error(GL_NO_ERROR);
}

void TextureGL::bindTexImage(egl::Surface *surface)
{
    UNIMPLEMENTED();
}

void TextureGL::releaseTexImage()
{
    UNIMPLEMENTED();
}

template <typename T>
static inline void SyncSamplerStateMember(const FunctionsGL *functions, const gl::SamplerState &newState,
                                          gl::SamplerState &curState, GLenum textureType, GLenum name,
                                          T(gl::SamplerState::*samplerMember))
{
    if (curState.*samplerMember != newState.*samplerMember)
    {
        curState.*samplerMember = newState.*samplerMember;
        functions->texParameterf(textureType, name, curState.*samplerMember);
    }
}

void TextureGL::syncSamplerState(const gl::SamplerState &samplerState) const
{
    if (mAppliedSamplerState != samplerState)
    {
        mStateManager->bindTexture(mTextureType, mTextureID);
        SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_MIN_FILTER, &gl::SamplerState::minFilter);
        SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_MAG_FILTER, &gl::SamplerState::magFilter);
        SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_WRAP_S, &gl::SamplerState::wrapS);
        SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_WRAP_T, &gl::SamplerState::wrapT);
        SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_WRAP_R, &gl::SamplerState::wrapR);
        SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_MAX_ANISOTROPY_EXT, &gl::SamplerState::maxAnisotropy);
        SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_BASE_LEVEL, &gl::SamplerState::baseLevel);
        SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_MAX_LEVEL, &gl::SamplerState::maxLevel);
        SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_MIN_LOD, &gl::SamplerState::minLod);
        SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_MAX_LOD, &gl::SamplerState::maxLod);
        SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_COMPARE_MODE, &gl::SamplerState::compareMode);
        SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_COMPARE_FUNC, &gl::SamplerState::compareFunc);
        SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_SWIZZLE_R, &gl::SamplerState::swizzleRed);
        SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_SWIZZLE_G, &gl::SamplerState::swizzleGreen);
        SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_SWIZZLE_B, &gl::SamplerState::swizzleBlue);
        SyncSamplerStateMember(mFunctions, samplerState, mAppliedSamplerState, mTextureType, GL_TEXTURE_SWIZZLE_A, &gl::SamplerState::swizzleAlpha);
    }
}

GLuint TextureGL::getTextureID() const
{
    return mTextureID;
}

}
<|endoftext|>


<commit_before>/******************************************************************************/
/* Copyright (c) 2013 VectorChief (at github, bitbucket, sourceforge)         */
/* Distributed under the MIT software license, see the accompanying           */
/* file COPYING or http://www.opensource.org/licenses/mit-license.php         */
/******************************************************************************/

#include "tracer.h"

/******************************************************************************/
/*********************************   UPDATE   *********************************/
/******************************************************************************/

/* This function is one of the backend's
 * global entry points (hence 0) used by the engine.
 * It updates surface's backend structures.
 */
rt_void update0(rt_SIMD_SURFACE *s_srf)
{

}

/******************************************************************************/
/*********************************   RENDER   *********************************/
/******************************************************************************/

/* This function is one of the backend's
 * global entry points (hence 0) used by the engine.
 * It renders the whole frame based on the data structures
 * prepared by the engine.
 */
rt_void render0(rt_SIMD_INFOX *s_inf)
{

/******************************************************************************/
/*********************************   ENTER   **********************************/
/******************************************************************************/

    ASM_ENTER(s_inf)

        movxx_mi(Mebp, inf_FRM_Y, IB(0))

    LBL(YY_cyc)

        movxx_ld(Reax, Mebp, inf_FRM_Y)
        mulxn_ld(Reax, Mebp, inf_FRM_ROW)
        shlxx_ri(Reax, IB(2))
        addxx_ld(Reax, Mebp, inf_FRAME)
        movxx_st(Reax, Mebp, inf_FRM)

        movxx_mi(Mebp, inf_FRM_X, IB(0))

    LBL(XX_cyc)

        movxx_ld(Reax, Mebp, inf_FRM_X)
        movxx_rr(Redx, Reax)
        shlxx_ri(Reax, IB(2))
        addxx_ld(Reax, Mebp, inf_FRM)

        /* fill with blue gradient for a test */
        shrxx_ri(Redx, IB(2))
        movxx_st(Redx, Oeax, PLAIN)
        addxx_ri(Reax, IB(4))
        movxx_st(Redx, Oeax, PLAIN)
        addxx_ri(Reax, IB(4))
        movxx_st(Redx, Oeax, PLAIN)
        addxx_ri(Reax, IB(4))
        movxx_st(Redx, Oeax, PLAIN)

    LBL(XX_end)

        addxx_mi(Mebp, inf_FRM_X, IB(4))

        movxx_ld(Reax, Mebp, inf_FRM_X)
        cmpxx_rm(Reax, Mebp, inf_FRM_W)
        jltxx_lb(XX_cyc)

    LBL(YY_end)

        addxx_mi(Mebp, inf_FRM_Y, IB(1))

        movxx_ld(Reax, Mebp, inf_FRM_Y)
        cmpxx_rm(Reax, Mebp, inf_FRM_H)
        jltxx_lb(YY_cyc)

    ASM_LEAVE(s_inf)

/******************************************************************************/
/*********************************   LEAVE   **********************************/
/******************************************************************************/

}

/******************************************************************************/
/******************************************************************************/
/******************************************************************************/
<commit_msg>add scene rendering<commit_after>/******************************************************************************/
/* Copyright (c) 2013 VectorChief (at github, bitbucket, sourceforge)         */
/* Distributed under the MIT software license, see the accompanying           */
/* file COPYING or http://www.opensource.org/licenses/mit-license.php         */
/******************************************************************************/

#include "tracer.h"
#include "format.h"
#include "system.h"

/******************************************************************************/
/*******************************   DEFINITIONS   ******************************/
/******************************************************************************/

/* Byte-offsets within SIMD-field
 * for packed scalar fields.
 */
#define PTR   0x00 /* LOCAL, PARAM, MAT_P, SRF_P */
#define FLG   0x04 /* LOCAL, MAT_P */
#define TAG   0x0C /* SRF_P */

/******************************************************************************/
/*********************************   MACROS   *********************************/
/******************************************************************************/

/* Perform axis mapping when
 * transform is a multiple of 90 degree rotation.
 */
#define INDEX_AXIS(nx)                                                      \
        movxx_ld(Reax, Mebx, srf_A_SGN(nx * 4))                             \
        movpx_ld(Xmm0, Iebx, srf_SBASE)                                     \
        movxx_ld(Reax, Mebx, srf_A_MAP(nx * 4))

#define MOVXR_LD(RG, RM, DP)                                                \
        movpx_ld(W(RG), W(RM), W(DP))                                       \
        xorpx_rr(W(RG), Xmm0)

#define MOVXR_ST(RG, RM, DP)                                                \
        xorpx_rr(W(RG), Xmm0)                                               \
        movpx_st(W(RG), W(RM), W(DP))

#define MOVZR_ST(RG, RM, DP)                                                \
        xorpx_rr(W(RG), W(RG))                                              \
        movpx_st(W(RG), W(RM), W(DP))

/* Context flags.
 * Check if flag "fl" is set in the context's field "pl",
 * jump to "lb" otherwise.
 */
#define FLAG_SIDE_OUTER     0
#define FLAG_SIDE_INNER     1
#define FLAG_SIDE           1

#define CHECK_FLAG(lb, pl, fl)                                              \
        movxx_ld(Reax, Mecx, ctx_##pl(FLG))                                 \
        andxx_ri(Reax, IB(fl))                                              \
        cmpxx_ri(Reax, IB(0))                                               \
        jeqxx_lb(lb)

/* Update relevant fragments of the
 * color and depth SIMD-fields accumulating values
 * over multiple passes from the respective SIMD-fields
 * in the context based on the current SIMD-mask and
 * the current depth values. Also perform
 * pointer dereferencing for color fetching.
 */
#define PAINT_FRAG(lb, pn)                                                  \
        cmpxx_mi(Mecx, ctx_TMASK(0x##pn), IB(0))                            \
        jeqxx_lb(lb##pn)                                                    \
        movxx_ld(Reax, Mecx, ctx_T_VAL(0x##pn))                             \
        movxx_st(Reax, Mecx, ctx_T_BUF(0x##pn))                             \
        movxx_ld(Reax, Mecx, ctx_C_PTR(0x##pn))                             \
        movxx_ld(Reax, Oeax, PLAIN)                                         \
        movxx_st(Reax, Mecx, ctx_C_BUF(0x##pn))                             \
    LBL(lb##pn)

#define PAINT_SIMD(lb)                                                      \
        PAINT_FRAG(lb, 00)                                                  \
        PAINT_FRAG(lb, 04)                                                  \
        PAINT_FRAG(lb, 08)                                                  \
        PAINT_FRAG(lb, 0C)

/* Flush all fragments of
 * the fully computed color SIMD-field from the context
 * into the framebuffer.
 */
#define FRAME_SIMD()                                                        \
        movpx_ld(Xmm0, Mecx, ctx_C_BUF(0))                                  \
        movpx_st(Xmm0, Oeax, PLAIN)

/* Replicate subroutine calling behaviour
 * by saving a given return address "lb" in the context's
 * local PTR field, then jumping to the destination address "to".
 * The destination code segment uses saved return address
 * to jump back after processing is finished. Parameters are
 * passed via context's local FLG field.
 */
#define SUBROUTINE(lb, to)                                                  \
        adrxx_lb(lb)                                                        \
        movxx_st(Reax, Mecx, ctx_LOCAL(PTR))                                \
        jmpxx_lb(to)                                                        \
    LBL(lb)

/******************************************************************************/
/*********************************   UPDATE   *********************************/
/******************************************************************************/

/* Local pointer tables
 * for quick entry point resolution.
 */
static
rt_pntr t_ptr[RT_TAG_SURFACE_MAX];

/* Backend's global entry point (hence 0).
 * Update surfaces's backend data.
 */
rt_void update0(rt_SIMD_SURFACE *s_srf)
{
    rt_word tag = (rt_word)s_srf->srf_p[3];

    if (tag >= RT_TAG_SURFACE_MAX)
    {
        return;
    }

    s_srf->srf_p[0] = t_ptr[tag];
}

/******************************************************************************/
/*********************************   RENDER   *********************************/
/******************************************************************************/

/* Backend's global entry point (hence 0).
 * Render the frame based on the data structures
 * prepared by the engine.
 */
rt_void render0(rt_SIMD_INFOX *s_inf)
{

/******************************************************************************/
/**********************************   ENTER   *********************************/
/******************************************************************************/

    ASM_ENTER(s_inf)

        cmpxx_mi(Mebp, inf_CTX, IB(0))
        jeqxx_lb(fetch_ptr)

        movxx_ld(Recx, Mebp, inf_CTX)
        movxx_ld(Redx, Mebp, inf_CAM)

        jmpxx_lb(XX_set)

    LBL(XX_ret)

/******************************************************************************/
/********************************   RAY INIT   ********************************/
/******************************************************************************/

        movpx_ld(Xmm0, Medx, cam_DIR_X)         /* ray_x <- DIR_X */
        movpx_st(Xmm0, Mecx, ctx_RAY_X)         /* ray_x -> RAY_X */

        movpx_ld(Xmm0, Medx, cam_DIR_Y)         /* ray_y <- DIR_Y */
        movpx_st(Xmm0, Mecx, ctx_RAY_Y)         /* ray_y -> RAY_Y */

        movpx_ld(Xmm0, Medx, cam_DIR_Z)         /* ray_z <- DIR_Z */
        movpx_st(Xmm0, Mecx, ctx_RAY_Z)         /* ray_z -> RAY_Z */

/******************************************************************************/
/********************************   VER SCAN   ********************************/
/******************************************************************************/

        movxx_mi(Mebp, inf_FRM_Y, IB(0))

    LBL(YY_cyc)

        movxx_ld(Reax, Mebp, inf_FRM_Y)
        mulxn_ld(Reax, Mebp, inf_FRM_ROW)
        shlxx_ri(Reax, IB(2))
        addxx_ld(Reax, Mebp, inf_FRAME)
        movxx_st(Reax, Mebp, inf_FRM)

/******************************************************************************/
/********************************   HOR SCAN   ********************************/
/******************************************************************************/

        movxx_mi(Mebp, inf_FRM_X, IB(0))

    LBL(XX_cyc)

        movxx_ld(Redx, Mebp, inf_CAM)

        movpx_ld(Xmm0, Medx, cam_T_MAX)         /* tmp_v <- T_MAX */
        movpx_st(Xmm0, Mecx, ctx_T_BUF(0))      /* tmp_v -> T_BUF */

        xorpx_rr(Xmm0, Xmm0)                    /* tmp_v <- 0     */
        movpx_st(Xmm0, Mecx, ctx_C_BUF(0))      /* tmp_v -> C_BUF */

/******************************************************************************/
/********************************   OBJ LIST   ********************************/
/******************************************************************************/

        movxx_ld(Resi, Mebp, inf_LST)

    LBL(OO_cyc)

        cmpxx_ri(Resi, IB(0))
        jeqxx_lb(OO_out)

        movxx_ld(Rebx, Mesi, elm_SIMD)

        movpx_ld(Xmm1, Mebx, srf_POS_X)
        movpx_ld(Xmm2, Mebx, srf_POS_Y)
        movpx_ld(Xmm3, Mebx, srf_POS_Z)

        subps_ld(Xmm1, Mecx, ctx_ORG_X)
        subps_ld(Xmm2, Mecx, ctx_ORG_Y)
        subps_ld(Xmm3, Mecx, ctx_ORG_Z)

        movpx_st(Xmm1, Mecx, ctx_DFF_X)
        movpx_st(Xmm2, Mecx, ctx_DFF_Y)
        movpx_st(Xmm3, Mecx, ctx_DFF_Z)

        jmpxx_mm(Mebx, srf_SRF_P(PTR))

    LBL(fetch_ptr)

        jmpxx_lb(fetch_PL_ptr)

/******************************************************************************/
/********************************   CLIPPING   ********************************/
/******************************************************************************/

    LBL(CC_clp)

        /* depth testing */
        movpx_ld(Xmm0, Mecx, ctx_T_BUF(0))      /* t_buf <- T_BUF */
        cgtps_rr(Xmm0, Xmm4)                    /* t_buf >! t_rt1 */
        andpx_rr(Xmm7, Xmm0)                    /* tmask &= gmask */

        /* ray clipping */
        movpx_ld(Xmm0, Mecx, ctx_T_MIN)         /* t_min <- T_MIN */
        cltps_rr(Xmm0, Xmm4)                    /* t_min <! t_rt1 */
        andpx_rr(Xmm7, Xmm0)                    /* tmask &= lmask */

        /* "x" section */
        movpx_ld(Xmm4, Mecx, ctx_RAY_X)         /* ray_x <- RAY_X */
        mulps_ld(Xmm4, Mecx, ctx_T_VAL(0))      /* ray_x *= t_rt1 */
        addps_ld(Xmm4, Mecx, ctx_ORG_X)         /* hit_x += ORG_X */
        movpx_st(Xmm4, Mecx, ctx_HIT_X)         /* hit_x -> HIT_X */

        /* "y" section */
        movpx_ld(Xmm5, Mecx, ctx_RAY_Y)         /* ray_y <- RAY_Y */
        mulps_ld(Xmm5, Mecx, ctx_T_VAL(0))      /* ray_y *= t_rt1 */
        addps_ld(Xmm5, Mecx, ctx_ORG_Y)         /* hit_y += ORG_Y */
        movpx_st(Xmm5, Mecx, ctx_HIT_Y)         /* hit_y -> HIT_Y */

        /* "z" section */
        movpx_ld(Xmm6, Mecx, ctx_RAY_Z)         /* ray_z <- RAY_Z */
        mulps_ld(Xmm6, Mecx, ctx_T_VAL(0))      /* ray_z *= t_rt1 */
        addps_ld(Xmm6, Mecx, ctx_ORG_Z)         /* hit_z += ORG_Z */
        movpx_st(Xmm6, Mecx, ctx_HIT_Z)         /* hit_z -> HIT_Z */

        jmpxx_mm(Mecx, ctx_LOCAL(PTR))

/******************************************************************************/
/********************************   MATERIAL   ********************************/
/******************************************************************************/

    LBL(MT_mat)

        movxx_ld(Reax, Mecx, ctx_LOCAL(FLG))
        andxx_ri(Reax, IB(FLAG_SIDE))
        shlxx_ri(Reax, IB(3))
        movxx_ld(Redx, Iebx, srf_MAT_P(PTR))

        /* load color */
        movpx_ld(Xmm0, Medx, mat_TEX_P)         /* tex_p <- TEX_P */

        /* store result */
        movpx_st(Xmm0, Mecx, ctx_C_PTR(0))      /* tex_c -> C_PTR */
        PAINT_SIMD(MT_rtx)

        jmpxx_mm(Mecx, ctx_LOCAL(PTR))

/******************************************************************************/
/**********************************   PLANE   *********************************/
/******************************************************************************/

    LBL(fetch_PL_ptr)

        adrxx_lb(PL_ptr)
        movxx_st(Reax, Mebp, inf_PTR_PL)
        jmpxx_lb(fetch_end)

    LBL(PL_ptr)

        /* "k" section */
        INDEX_AXIS(RT_K)                        /* eax   <-     k */
        MOVXR_LD(Xmm4, Iecx, ctx_DFF_O)         /* dff_k <- DFF_K */
        MOVXR_LD(Xmm3, Iecx, ctx_RAY_O)         /* ray_k <- RAY_K */

        /* create xmask */
        xorpx_rr(Xmm7, Xmm7)                    /* xmask <- 0     */
        cneps_rr(Xmm7, Xmm3)                    /* xmask != ray_k */

        /* "tt" section */
        divps_rr(Xmm4, Xmm3)                    /* dff_k /= ray_k */
        movpx_st(Xmm4, Mecx, ctx_T_VAL(0))      /* t_rt1 -> T_VAL */

        /* clipping */
        SUBROUTINE(PL_cp1, CC_clp)
        CHECK_MASK(OO_end, NONE, Xmm7)
        movpx_st(Xmm7, Mecx, ctx_WMASK)         /* xmask -> WMASK */

        INDEX_AXIS(RT_K)
        MOVXR_LD(Xmm3, Iecx, ctx_RAY_O)         /* ray_k <- RAY_K */
        xorpx_rr(Xmm0, Xmm0)                    /* tmp_v <- 0     */

/******************************************************************************/
/*  LBL(PL_rt1)  */

        /* outer side */
        cltps_rr(Xmm3, Xmm0)                    /* ray_k <! tmp_v */
        andpx_rr(Xmm7, Xmm3)                    /* tmask &= lmask */
        movpx_st(Xmm7, Mecx, ctx_TMASK(0))      /* tmask -> TMASK */
        CHECK_MASK(PL_rt2, NONE, Xmm7)

        /* material */
        movxx_mi(Mecx, ctx_LOCAL(FLG), IB(FLAG_SIDE_OUTER))
        SUBROUTINE(PL_mt1, MT_mat)

/******************************************************************************/
    LBL(PL_rt2)

        /* inner side */
        movpx_ld(Xmm7, Mecx, ctx_TMASK(0))      /* tmask <- TMASK */
        xorpx_ld(Xmm7, Mecx, ctx_WMASK)         /* tmask ^= WMASK */
        CHECK_MASK(OO_end, NONE, Xmm7)
        movpx_st(Xmm7, Mecx, ctx_TMASK(0))      /* tmask -> TMASK */

        /* material */
        movxx_mi(Mecx, ctx_LOCAL(FLG), IB(FLAG_SIDE_INNER))
        SUBROUTINE(PL_mt2, MT_mat)

        jmpxx_lb(OO_end)

/******************************************************************************/
/*********************************   OBJECT   *********************************/
/******************************************************************************/

    LBL(OO_end)

        movxx_ld(Resi, Mesi, elm_NEXT)
        jmpxx_lb(OO_cyc)

    LBL(OO_out)

        jmpxx_mm(Mecx, ctx_PARAM(PTR))

/******************************************************************************/
/*********************************   CAMERA   *********************************/
/******************************************************************************/

    LBL(XX_set)

        adrxx_lb(XX_end)
        movxx_st(Reax, Mecx, ctx_PARAM(PTR))
        jmpxx_lb(XX_ret)

    LBL(XX_end)

        movxx_ld(Redx, Mebp, inf_CAM)

        movxx_ld(Reax, Mebp, inf_FRM_X)
        shlxx_ri(Reax, IB(2))
        addxx_ld(Reax, Mebp, inf_FRM)
        FRAME_SIMD()
        addxx_mi(Mebp, inf_FRM_X, IB(4))

        movxx_ld(Reax, Mebp, inf_FRM_X)
        cmpxx_rm(Reax, Mebp, inf_FRM_W)
        jeqxx_lb(YY_end)

        movxx_ld(Redx, Mebp, inf_CAM)

        movpx_ld(Xmm0, Mecx, ctx_RAY_X)         /* ray_x <- RAY_X */
        addps_ld(Xmm0, Medx, cam_HOR_X)         /* ray_x += HOR_X */
        movpx_st(Xmm0, Mecx, ctx_RAY_X)         /* ray_x -> RAY_X */

        movpx_ld(Xmm1, Mecx, ctx_RAY_Y)         /* ray_y <- RAY_Y */
        addps_ld(Xmm1, Medx, cam_HOR_Y)         /* ray_y += HOR_Y */
        movpx_st(Xmm1, Mecx, ctx_RAY_Y)         /* ray_y -> RAY_Y */

        movpx_ld(Xmm2, Mecx, ctx_RAY_Z)         /* ray_z <- RAY_Z */
        addps_ld(Xmm2, Medx, cam_HOR_Z)         /* ray_z += HOR_Z */
        movpx_st(Xmm2, Mecx, ctx_RAY_Z)         /* ray_z -> RAY_Z */

        jmpxx_lb(XX_cyc)

/******************************************************************************/
/*********************************   CAMERA   *********************************/
/******************************************************************************/

    LBL(YY_end)

        movxx_ld(Redx, Mebp, inf_CAM)

        movpx_ld(Xmm0, Medx, cam_DIR_X)         /* ray_x <- DIR_X */
        addps_ld(Xmm0, Medx, cam_VER_X)         /* ray_x += VER_X */
        movpx_st(Xmm0, Medx, cam_DIR_X)         /* ray_x -> DIR_X */
        movpx_st(Xmm0, Mecx, ctx_RAY_X)         /* ray_x -> RAY_X */

        movpx_ld(Xmm1, Medx, cam_DIR_Y)         /* ray_y <- DIR_Y */
        addps_ld(Xmm1, Medx, cam_VER_Y)         /* ray_y += VER_Y */
        movpx_st(Xmm1, Medx, cam_DIR_Y)         /* ray_y -> DIR_Y */
        movpx_st(Xmm1, Mecx, ctx_RAY_Y)         /* ray_y -> RAY_Y */

        movpx_ld(Xmm2, Medx, cam_DIR_Z)         /* ray_z <- DIR_Z */
        addps_ld(Xmm2, Medx, cam_VER_Z)         /* ray_z += VER_Z */
        movpx_st(Xmm2, Medx, cam_DIR_Z)         /* ray_z -> DIR_Z */
        movpx_st(Xmm2, Mecx, ctx_RAY_Z)         /* ray_z -> RAY_Z */

        movxx_ri(Reax, IB(1))
        addxx_st(Reax, Mebp, inf_FRM_Y)

        movxx_ld(Reax, Mebp, inf_FRM_Y)
        cmpxx_rm(Reax, Mebp, inf_FRM_H)
        jltxx_lb(YY_cyc)

    LBL(fetch_end)

    ASM_LEAVE(s_inf)

/******************************************************************************/
/**********************************   LEAVE   *********************************/
/******************************************************************************/

    if (s_inf->ctx != RT_NULL)
    {
        return;
    }

    t_ptr[RT_TAG_PLANE] = s_inf->ptr_pl;

    /* RT_LOGI("PL ptr = %p\n", s_inf->ptr_pl); */
}

/******************************************************************************/
/******************************************************************************/
/******************************************************************************/
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/

#include "fileinprojectfinder.h"
#include <utils/qtcassert.h>

#include <QtCore/QFileInfo>
#include <QtCore/QUrl>

namespace Utils {

/*!
  \class Utils::FileInProjectFinder

  \brief Helper class to find the 'original' file in the project directory for a given file url.

  Often files are copied in the build + deploy process. findFile() searches for an existing file
  in the project directory for a given file path:

  E.g. following file paths:
  \list
  \i C:/app-build-desktop/qml/app/main.qml (shadow build directory)
  \i C:/Private/e3026d63/qml/app/main.qml  (Application data folder on Symbian device)
  \i /Users/x/app-build-desktop/App.app/Contents/Resources/qml/App/main.qml (folder on Mac OS X)
  \endlist

 should all be mapped to $PROJECTDIR/qml/app/main.qml
*/

FileInProjectFinder::FileInProjectFinder()
{
}

void FileInProjectFinder::setProjectDirectory(const QString &absoluteProjectPath)
{
    QTC_ASSERT(QFileInfo(absoluteProjectPath).exists()
               && QFileInfo(absoluteProjectPath).isAbsolute(), return);

    if (absoluteProjectPath == m_projectDir)
        return;

    m_projectDir = absoluteProjectPath;
    while (m_projectDir.endsWith(QLatin1Char('/')))
        m_projectDir.remove(m_projectDir.length() - 1, 1);

    m_cache.clear();
}

QString FileInProjectFinder::projectDirectory() const
{
    return m_projectDir;
}

void FileInProjectFinder::setProjectFiles(const QStringList &projectFiles)
{
    m_projectFiles = projectFiles;
    m_cache.clear();
}

/**
  Returns the best match for the given file url in the project directory.

  The method first checks whether the file inside the project directory exists.
  If not, the leading directory in the path is stripped, and the - now shorter - path is
  checked for existence. This continues until either the file is found, or the relative path
  does not contain any directories any more: In this case the path of the url is returned.

  Second, we walk the list of project files, and search for a file name match there.
  */
QString FileInProjectFinder::findFile(const QUrl &fileUrl, bool *success) const
{
    QString originalPath = fileUrl.toLocalFile();
    if (originalPath.isEmpty()) // e.g. qrc://
        originalPath = fileUrl.path();

    if (originalPath.isEmpty()) {
        if (success)
            success = false;
        return originalPath;
    }

    if (!m_projectDir.isEmpty()) {
        int prefixToIgnore = -1;
        const QChar separator = QLatin1Char('/');
        if (originalPath.startsWith(m_projectDir + separator)) {
#ifdef Q_OS_MAC
            // starting with the project path is not sufficient if the file was
            // copied in an insource build, e.g. into MyApp.app/Contents/Resources
            static const QString appResourcePath = QString::fromLatin1(".app/Contents/Resources");
            if (originalPath.contains(appResourcePath)) {
                // the path is inside the project, but most probably as a resource of an insource build
                // so ignore that path
                prefixToIgnore = originalPath.indexOf(appResourcePath) + appResourcePath.length();
            } else {
#endif
                if (success)
                    *success = true;
                return originalPath;
#ifdef Q_OS_MAC
            }
#endif
        }

        if (m_cache.contains(originalPath)) {
            // check if cached path is still there
            QString candidate = m_cache.value(originalPath);
            QFileInfo candidateInfo(candidate);
            if (candidateInfo.exists() && candidateInfo.isFile()) {
                if (success)
                    *success = true;
                return candidate;
            }
        }

        // Strip directories one by one from the beginning of the path,
        // and see if the new relative path exists in the build directory.
        if (prefixToIgnore < 0) {
            if (!QFileInfo(originalPath).isAbsolute()
                    && !originalPath.startsWith(separator)) {
                prefixToIgnore = 0;
            } else {
                prefixToIgnore = originalPath.indexOf(separator);
            }
        }
        while (prefixToIgnore != -1) {
            QString candidate = originalPath;
            candidate.remove(0, prefixToIgnore);
            candidate.prepend(m_projectDir);
            QFileInfo candidateInfo(candidate);
            if (candidateInfo.exists() && candidateInfo.isFile()) {
                if (success)
                    *success = true;

                m_cache.insert(originalPath, candidate);
                return candidate;
            }
            prefixToIgnore = originalPath.indexOf(separator, prefixToIgnore + 1);
        }
    }

    const QString fileName = QFileInfo(originalPath).fileName();
    foreach (const QString &f, m_projectFiles) {
        if (QFileInfo(f).fileName() == fileName) {
            m_cache.insert(originalPath, f);
            if (success)
                *success = true;
            return f;
        }
    }

    if (success)
        *success = false;

    return originalPath;
}

} // namespace Utils
<commit_msg>Fix *bool assignment<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/

#include "fileinprojectfinder.h"
#include <utils/qtcassert.h>

#include <QtCore/QFileInfo>
#include <QtCore/QUrl>

namespace Utils {

/*!
  \class Utils::FileInProjectFinder

  \brief Helper class to find the 'original' file in the project directory for a given file url.

  Often files are copied in the build + deploy process. findFile() searches for an existing file
  in the project directory for a given file path:

  E.g. following file paths:
  \list
  \i C:/app-build-desktop/qml/app/main.qml (shadow build directory)
  \i C:/Private/e3026d63/qml/app/main.qml  (Application data folder on Symbian device)
  \i /Users/x/app-build-desktop/App.app/Contents/Resources/qml/App/main.qml (folder on Mac OS X)
  \endlist

 should all be mapped to $PROJECTDIR/qml/app/main.qml
*/

FileInProjectFinder::FileInProjectFinder()
{
}

void FileInProjectFinder::setProjectDirectory(const QString &absoluteProjectPath)
{
    QTC_ASSERT(QFileInfo(absoluteProjectPath).exists()
               && QFileInfo(absoluteProjectPath).isAbsolute(), return);

    if (absoluteProjectPath == m_projectDir)
        return;

    m_projectDir = absoluteProjectPath;
    while (m_projectDir.endsWith(QLatin1Char('/')))
        m_projectDir.remove(m_projectDir.length() - 1, 1);

    m_cache.clear();
}

QString FileInProjectFinder::projectDirectory() const
{
    return m_projectDir;
}

void FileInProjectFinder::setProjectFiles(const QStringList &projectFiles)
{
    m_projectFiles = projectFiles;
    m_cache.clear();
}

/**
  Returns the best match for the given file url in the project directory.

  The method first checks whether the file inside the project directory exists.
  If not, the leading directory in the path is stripped, and the - now shorter - path is
  checked for existence. This continues until either the file is found, or the relative path
  does not contain any directories any more: In this case the path of the url is returned.

  Second, we walk the list of project files, and search for a file name match there.
  */
QString FileInProjectFinder::findFile(const QUrl &fileUrl, bool *success) const
{
    QString originalPath = fileUrl.toLocalFile();
    if (originalPath.isEmpty()) // e.g. qrc://
        originalPath = fileUrl.path();

    if (originalPath.isEmpty()) {
        if (success)
            *success = false;
        return originalPath;
    }

    if (!m_projectDir.isEmpty()) {
        int prefixToIgnore = -1;
        const QChar separator = QLatin1Char('/');
        if (originalPath.startsWith(m_projectDir + separator)) {
#ifdef Q_OS_MAC
            // starting with the project path is not sufficient if the file was
            // copied in an insource build, e.g. into MyApp.app/Contents/Resources
            static const QString appResourcePath = QString::fromLatin1(".app/Contents/Resources");
            if (originalPath.contains(appResourcePath)) {
                // the path is inside the project, but most probably as a resource of an insource build
                // so ignore that path
                prefixToIgnore = originalPath.indexOf(appResourcePath) + appResourcePath.length();
            } else {
#endif
                if (success)
                    *success = true;
                return originalPath;
#ifdef Q_OS_MAC
            }
#endif
        }

        if (m_cache.contains(originalPath)) {
            // check if cached path is still there
            QString candidate = m_cache.value(originalPath);
            QFileInfo candidateInfo(candidate);
            if (candidateInfo.exists() && candidateInfo.isFile()) {
                if (success)
                    *success = true;
                return candidate;
            }
        }

        // Strip directories one by one from the beginning of the path,
        // and see if the new relative path exists in the build directory.
        if (prefixToIgnore < 0) {
            if (!QFileInfo(originalPath).isAbsolute()
                    && !originalPath.startsWith(separator)) {
                prefixToIgnore = 0;
            } else {
                prefixToIgnore = originalPath.indexOf(separator);
            }
        }
        while (prefixToIgnore != -1) {
            QString candidate = originalPath;
            candidate.remove(0, prefixToIgnore);
            candidate.prepend(m_projectDir);
            QFileInfo candidateInfo(candidate);
            if (candidateInfo.exists() && candidateInfo.isFile()) {
                if (success)
                    *success = true;

                m_cache.insert(originalPath, candidate);
                return candidate;
            }
            prefixToIgnore = originalPath.indexOf(separator, prefixToIgnore + 1);
        }
    }

    const QString fileName = QFileInfo(originalPath).fileName();
    foreach (const QString &f, m_projectFiles) {
        if (QFileInfo(f).fileName() == fileName) {
            m_cache.insert(originalPath, f);
            if (success)
                *success = true;
            return f;
        }
    }

    if (success)
        *success = false;

    return originalPath;
}

} // namespace Utils
<|endoftext|>


<commit_before> /**
 * \file
 * \brief     Combination of the work of sprint 1
 * \author    Tim IJntema, Stefan de Beer, Arco Gelderblom, Rik Honcoop, Koen de Groot
 * \copyright Copyright (c) 2017, The R2D2 Team
 * \license   See LICENSE
 */

#include "mysql.hh"
#include "mfrc522.hh"
#include "encryption.hh"
#include "led-controller.hh"
#include "matrix-keypad.hh"

#include <wiringPi.h>
#include <wiringPiSPI.h>

#include <iostream>

int main(int argc, char **argv) {
    MySql connection;

    if(!connection.connectTo("192.168.2.50", "R2D2", "BB8")){
        std::cout << "Can not connect\n";
        exit(0);
    }

    if(!connection.selectDatabase("R2D2")){
        std::cout << "Database unknown\n";
        exit(0);
    }

    wiringPiSetup();
    wiringPiSPISetup(0, 10000000);//max speed for mfrc522 is 10Mhz
    Mfrc522 rfid;
    rfid.init();

    //Keypad pinSetup
    const int keypadRow[] = {29, 28, 27, 26};
    const int keypadColumn[] = {31, 11, 10, 6};

    //Keypad objects
    MatrixKeypad keypad(keypadRow, keypadColumn, 4);
    char c;

    Encryptie encryption(65341);

    LedController led;

    while(1){
        std::cout << "\n\nWaiting for rfid tag: \n";

        while(!rfid.isTagPresent()){}

        std::cout<<"Hello tag\n";

        while((c = keypad.getKey()) == 'h'){
            delay(100);
        }
        std::cout << "A key has been pressed\n";

        if(!connection.executeQuery("SELECT * FROM RFID")){
            std::cout << "Can not execute query\n";
            exit(0);
        }

        std::cout << "Database information: "
                  << connection.getPreviousResponseColumn("CARD_ID")
                  << '\n';

        std::cout << "String before encryption: R2D2 project\n";
        std::cout << "String after encryption: "
                  << encryption.Encrypt("R2D2 project")
                  << '\n';

        led.blinkLed(0, 5000);
    return 0;
}
<commit_msg>[RFID-01]fixed typo and syntax error<commit_after> /**
 * \file
 * \brief     Combination of the work of sprint 1
 * \author    Tim IJntema, Stefan de Beer, Arco Gelderblom, Rik Honcoop, Koen de Groot
 * \copyright Copyright (c) 2017, The R2D2 Team
 * \license   See LICENSE
 */

#include "mysql.hh"
#include "mfrc522.hh"
#include "encryption.hh"
#include "led-controller.hh"
#include "matrix-keypad.hh"

#include <wiringPi.h>
#include <wiringPiSPI.h>

#include <iostream>

int main(int argc, char **argv) {
    MySql connection;

    if(!connection.connectTo("192.168.2.50", "R2D2", "BB8")){
        std::cout << "Can not connect\n";
        exit(0);
    }

    if(!connection.selectDatabase("R2D2")){
        std::cout << "Database unknown\n";
        exit(0);
    }

    wiringPiSetup();
    wiringPiSPISetup(0, 10000000);//max speed for mfrc522 is 10Mhz
    Mfrc522 rfid;
    rfid.init();

    //Keypad pinSetup
    const int keypadRow[] = {29, 28, 27, 26};
    const int keypadColumn[] = {31, 11, 10, 6};

    //Keypad objects
    MatrixKeypad keypad(keypadRow, keypadColumn, 4);
    char c;

    Encryption encryption(65341);

    LedController led;

    while(1){
        std::cout << "\n\nWaiting for rfid tag: \n";

        while(!rfid.isTagPresent()){}

        std::cout<<"Hello tag\n";

        while((c = keypad.getKey()) == 'h'){
            delay(100);
        }
        std::cout << "A key has been pressed\n";

        if(!connection.executeQuery("SELECT * FROM RFID")){
            std::cout << "Can not execute query\n";
            exit(0);
        }

        std::cout << "Database information: "
                  << connection.getPreviousResponseColumn("CARD_ID")
                  << '\n';

        std::cout << "String before encryption: R2D2 project\n";
        std::cout << "String after encryption: "
                  << encryption.Encrypt("R2D2 project")
                  << '\n';

        led.blinkLed(0, 5000);
	}
return 0;
}
<|endoftext|>


<commit_before>#include "WidgetExplorer.h"

#include <QGLWidget>
#include <QKeyEvent>
#include <QTime>
#include <cmath>
#include <GL/glu.h>
#include <QThread>
#include "Scenery.h"
#include "SoftwareRenderer.h"
#include "OpenGLRenderer.h"
#include "WaterDefinition.h"
#include "SurfaceMaterial.h"
#include "tools/euclid.h"
#include "renderer.h"
#include "CameraDefinition.h"
#include "atmosphere/public.h"
#include "water/public.h"
#include "terrain/public.h"
#include "ExplorerChunkSky.h"
#include "ExplorerChunkTerrain.h"

class ChunkMaintenanceThread : public QThread
{
public:

    ChunkMaintenanceThread(WidgetExplorer* wanderer)
    {
        _wanderer = wanderer;
        _running = true;
    }

    void askStop()
    {
        _running = false;
    }

    static inline void usleep(unsigned long us)
    {
        QThread::usleep(us);
    }

protected:

    void run()
    {
        while (_running)
        {
            _wanderer->performChunksMaintenance();
            QThread::usleep(10000);
        }
    }

private:
    bool _running;
    WidgetExplorer* _wanderer;
};

static QVector<ChunkMaintenanceThread*> _threads;

static Vector3 _getCameraLocation(Renderer* renderer, Vector3)
{
    return ((CameraDefinition*)renderer->customData[2])->getLocation();
}

static AtmosphereResult _applyAerialPerspective(Renderer*, Vector3, Color base)
{
    AtmosphereResult result;
    atmosphereInitResult(&result);
    result.base = base;
    result.final = base;
    atmosphereUpdateResult(&result);
    return result;
}

WidgetExplorer::WidgetExplorer(QWidget *parent, CameraDefinition* camera, SoftwareRenderer* renderer) :
QGLWidget(parent)
{
    setMinimumSize(400, 300);
    setFocusPolicy(Qt::StrongFocus);

    _current_camera = new CameraDefinition;
    _base_camera = camera;
    camera->copy(_current_camera);

    if (renderer)
    {
        _renderer = renderer;
        _renderer_created = false;
    }
    else
    {
        _renderer = new SoftwareRenderer(Scenery::getCurrent());
        _renderer_created = true;
    }
    _opengl_renderer = new OpenGLRenderer(NULL);
    _renderer->prepare();
    _renderer->render_quality = 3;
    _renderer->customData[2] = _base_camera;
    _renderer->getCameraLocation = _getCameraLocation;
    _renderer->atmosphere->applyAerialPerspective = _applyAerialPerspective;
    lightingManagerDisableSpecularity(_renderer->lighting);

    _inited = false;
    _updated = false;

    _average_frame_time = 0.05;
    _quality = 3;
    _last_mouse_x = 0;
    _last_mouse_y = 0;

    startTimer(500);
}

WidgetExplorer::~WidgetExplorer()
{
    stopRendering();

    for (int i = 0; i < _chunks.count(); i++)
    {
        delete _chunks[i];
    }
    delete _current_camera;

    if (_renderer_created)
    {
        rendererDelete(_renderer);
    }
    delete _opengl_renderer;
}

void WidgetExplorer::startRendering()
{
    // Add terrain
    int chunks = 20;
    double size = 400.0;
    double chunksize = size / (double) chunks;
    double start = -size / 2.0;
    double water_height = _renderer->water->getHeightInfo(_renderer).base_height;
    for (int i = 0; i < chunks; i++)
    {
        for (int j = 0; j < chunks; j++)
        {
            ExplorerChunkTerrain* chunk = new ExplorerChunkTerrain(_renderer, start + chunksize * (double) i, start + chunksize * (double) j, chunksize, chunks, water_height);
            _chunks.append(chunk);
            _updateQueue.append(chunk);
        }
    }

    // Add skybox
    for (int orientation = 0; orientation < 5; orientation++)
    {
        ExplorerChunkSky* chunk = new ExplorerChunkSky(_renderer, 500.0, (SkyboxOrientation) orientation);
        _chunks.append(chunk);
        _updateQueue.append(chunk);
    }

    // Start rendering workers
    int nbcore;
    _alive = true;

    nbcore = QThread::idealThreadCount();
    if (nbcore < 1)
    {
        nbcore = 1;
    }

    for (int i = 0; i < nbcore; i++)
    {
        _threads.append(new ChunkMaintenanceThread(this));
    }
    for (int i = 0; i < _threads.count(); i++)
    {
        _threads[i]->start();
    }
}

void WidgetExplorer::stopRendering()
{
    for (int i = 0; i < _threads.count(); i++)
    {
        _threads[i]->askStop();
    }
    _alive = false;
    for (int i = 0; i < _threads.count(); i++)
    {
        _threads[i]->wait();
    }
}

bool _cmpChunks(const BaseExplorerChunk* c1, const BaseExplorerChunk* c2)
{
    return c1->priority > c2->priority;
}

void WidgetExplorer::performChunksMaintenance()
{
    BaseExplorerChunk* chunk;

    _lock_chunks.lock();
    if (_updateQueue.count() > 0)
    {
        chunk = _updateQueue.takeFirst();
        _lock_chunks.unlock();
    }
    else
    {
        _lock_chunks.unlock();
        return;
    }

    if (chunk->maintain())
    {
        if (!_alive)
        {
            return;
        }

        _updated = true;
    }

    _lock_chunks.lock();
    _updateQueue.append(chunk);
    _lock_chunks.unlock();
}

void WidgetExplorer::resetCamera()
{
    _base_camera->copy(_current_camera);
    updateGL();
}

void WidgetExplorer::validateCamera()
{
    _current_camera->copy(_base_camera);
}

void WidgetExplorer::keyPressEvent(QKeyEvent* event)
{
    double factor;

    if (event->modifiers() & Qt::ControlModifier)
    {
        factor = 0.1;
    }
    else if (event->modifiers() & Qt::ShiftModifier)
    {
        factor = 10.0;
    }
    else
    {
        factor = 1.0;
    }
    factor *= 3.0;

    if (event->key() == Qt::Key_Up)
    {
        _current_camera->strafeForward(0.1 * factor);
        updateGL();
    }
    else if (event->key() == Qt::Key_Down)
    {
        _current_camera->strafeForward(-0.1 * factor);
        updateGL();
    }
    else if (event->key() == Qt::Key_Right)
    {
        _current_camera->strafeRight(0.1 * factor);
        updateGL();
    }
    else if (event->key() == Qt::Key_Left)
    {
        _current_camera->strafeRight(-0.1 * factor);
        updateGL();
    }
    else if (event->key() == Qt::Key_PageUp)
    {
        _current_camera->strafeUp(0.1 * factor);
        updateGL();
    }
    else if (event->key() == Qt::Key_PageDown)
    {
        _current_camera->strafeUp(-0.1 * factor);
        updateGL();
    }
    else
    {
        QGLWidget::keyPressEvent(event);
    }
}

void WidgetExplorer::mousePressEvent(QMouseEvent* event)
{
    _last_mouse_x = event->x();
    _last_mouse_y = event->y();

    event->ignore();
}

void WidgetExplorer::mouseMoveEvent(QMouseEvent* event)
{
    double factor;

    if (event->modifiers() & Qt::ControlModifier)
    {
        factor = 0.01;
    }
    else if (event->modifiers() & Qt::ShiftModifier)
    {
        factor = 1.0;
    }
    else
    {
        factor = 0.1;
    }
    factor *= 0.2;

    if (event->buttons() & Qt::LeftButton)
    {
        _current_camera->rotateYaw((double) (event->x() - _last_mouse_x) * factor * 0.1);
        _current_camera->rotatePitch((double) (event->y() - _last_mouse_y) * factor * 0.1);
        updateGL();
        event->accept();
    }
    else if (event->buttons() & Qt::RightButton)
    {
        _current_camera->strafeRight((double) (_last_mouse_x - event->x()) * factor);
        _current_camera->strafeUp((double) (event->y() - _last_mouse_y) * factor);
        updateGL();
        event->accept();
    }
    else
    {
        event->ignore();
    }

    _last_mouse_x = event->x();
    _last_mouse_y = event->y();
}

void WidgetExplorer::wheelEvent(QWheelEvent* event)
{
    double factor;

    if (event->modifiers() & Qt::ControlModifier)
    {
        factor = 0.01;
    }
    else if (event->modifiers() & Qt::ShiftModifier)
    {
        factor = 1.0;
    }
    else
    {
        factor = 0.1;
    }
    factor *= 0.03;

    if (event->orientation() == Qt::Vertical)
    {
        _current_camera->strafeForward((double) event->delta() * factor);
        updateGL();
    }
    event->accept();
}

void WidgetExplorer::timerEvent(QTimerEvent*)
{
    if (!_inited)
    {
        _inited = true;
        startRendering();
    }

    if (_updated)
    {
        _updated = false;
        updateGL();
    }

    for (int i = 0; i < _chunks.count(); i++)
    {
        _chunks[i]->updatePriority(_current_camera);
    }
    _lock_chunks.lock();
    qSort(_updateQueue.begin(), _updateQueue.end(), _cmpChunks);
    _lock_chunks.unlock();
}

void WidgetExplorer::initializeGL()
{
    _opengl_renderer->initialize();
}

void WidgetExplorer::resizeGL(int w, int h)
{
    _current_camera->setRenderSize(w, h);
    _opengl_renderer->resize(w, h);
}

void WidgetExplorer::paintGL()
{
    GLenum error_code;
    QTime start_time;
    double frame_time;
    WaterDefinition* water = _renderer->water->definition;

    // Don't do this at each frame, only on camera change
    _renderer->getScenery()->setCamera(_current_camera);

    start_time = QTime::currentTime();

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    Vector3 camera_location = _current_camera->getLocation();
    Vector3 camera_target = _current_camera->getTarget();
    Vector3 camera_up = _current_camera->getUpVector();
    gluLookAt(camera_location.x, camera_location.y, camera_location.z, camera_target.x, camera_target.y, camera_target.z, camera_up.x, camera_up.y, camera_up.z);

    // Background
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Render water
    double water_height = _renderer->terrain->getWaterHeight(_renderer);
    glDisable(GL_TEXTURE_2D);
    glColor3f(water->material->_rgb.r, water->material->_rgb.g, water->material->_rgb.b);
    glBegin(GL_QUADS);
    glVertex3f(camera_location.x - 500.0, water_height, camera_location.z - 500.0);
    glVertex3f(camera_location.x - 500.0, water_height, camera_location.z + 500.0);
    glVertex3f(camera_location.x + 500.0, water_height, camera_location.z + 500.0);
    glVertex3f(camera_location.x + 500.0, water_height, camera_location.z - 500.0);
    glEnd();

    // Render chunks
    glEnable(GL_TEXTURE_2D);
    for (int i = 0; i < _chunks.count(); i++)
    {
        glColor3f(1.0, 1.0, 1.0);
        _chunks[i]->render(this);
    }

    frame_time = 0.001 * (double) start_time.msecsTo(QTime::currentTime());

    _average_frame_time = _average_frame_time * 0.8 + frame_time * 0.2;
    //printf("%d %f\n", quality, average_frame_time);

    if (_average_frame_time > 0.1 && _quality > 1)
    {
        _quality--;
    }
    if (_average_frame_time < 0.04 && _quality < 10)
    {
        _quality++;
    }

    // Messages
    if (!_inited)
    {
        glColor3f(0.0, 0.0, 0.0);
        renderText(6, height() - 10, tr("Please wait while loading scene..."));
        glColor3f(1.0, 1.0, 1.0);
        renderText(5, height() - 9, tr("Please wait while loading scene..."));
    }

    while ((error_code = glGetError()) != GL_NO_ERROR)
    {
        qDebug("[OpenGL] ERROR : %s", (const char*)gluErrorString(error_code));
    }
}
<commit_msg>Fixed camera above ground checking in opengl renderer<commit_after>#include "WidgetExplorer.h"

#include <QGLWidget>
#include <QKeyEvent>
#include <QTime>
#include <cmath>
#include <GL/glu.h>
#include <QThread>
#include "Scenery.h"
#include "SoftwareRenderer.h"
#include "OpenGLRenderer.h"
#include "WaterDefinition.h"
#include "SurfaceMaterial.h"
#include "tools/euclid.h"
#include "renderer.h"
#include "CameraDefinition.h"
#include "atmosphere/public.h"
#include "water/public.h"
#include "terrain/public.h"
#include "ExplorerChunkSky.h"
#include "ExplorerChunkTerrain.h"

class ChunkMaintenanceThread : public QThread
{
public:

    ChunkMaintenanceThread(WidgetExplorer* wanderer)
    {
        _wanderer = wanderer;
        _running = true;
    }

    void askStop()
    {
        _running = false;
    }

    static inline void usleep(unsigned long us)
    {
        QThread::usleep(us);
    }

protected:

    void run()
    {
        while (_running)
        {
            _wanderer->performChunksMaintenance();
            QThread::usleep(10000);
        }
    }

private:
    bool _running;
    WidgetExplorer* _wanderer;
};

static QVector<ChunkMaintenanceThread*> _threads;

static Vector3 _getCameraLocation(Renderer* renderer, Vector3)
{
    return ((CameraDefinition*)renderer->customData[2])->getLocation();
}

static AtmosphereResult _applyAerialPerspective(Renderer*, Vector3, Color base)
{
    AtmosphereResult result;
    atmosphereInitResult(&result);
    result.base = base;
    result.final = base;
    atmosphereUpdateResult(&result);
    return result;
}

WidgetExplorer::WidgetExplorer(QWidget *parent, CameraDefinition* camera, SoftwareRenderer* renderer) :
QGLWidget(parent)
{
    setMinimumSize(400, 300);
    setFocusPolicy(Qt::StrongFocus);

    _current_camera = new CameraDefinition;
    _base_camera = camera;
    camera->copy(_current_camera);

    if (renderer)
    {
        _renderer = renderer;
        _renderer_created = false;
    }
    else
    {
        _renderer = new SoftwareRenderer(Scenery::getCurrent());
        _renderer_created = true;
    }
    _opengl_renderer = new OpenGLRenderer(NULL);
    _renderer->prepare();
    _renderer->render_quality = 3;
    _renderer->customData[2] = _base_camera;
    _renderer->getCameraLocation = _getCameraLocation;
    _renderer->atmosphere->applyAerialPerspective = _applyAerialPerspective;
    lightingManagerDisableSpecularity(_renderer->lighting);

    _inited = false;
    _updated = false;

    _average_frame_time = 0.05;
    _quality = 3;
    _last_mouse_x = 0;
    _last_mouse_y = 0;

    startTimer(500);
}

WidgetExplorer::~WidgetExplorer()
{
    stopRendering();

    for (int i = 0; i < _chunks.count(); i++)
    {
        delete _chunks[i];
    }
    delete _current_camera;

    if (_renderer_created)
    {
        rendererDelete(_renderer);
    }
    delete _opengl_renderer;
}

void WidgetExplorer::startRendering()
{
    // Add terrain
    int chunks = 20;
    double size = 400.0;
    double chunksize = size / (double) chunks;
    double start = -size / 2.0;
    double water_height = _renderer->water->getHeightInfo(_renderer).base_height;
    for (int i = 0; i < chunks; i++)
    {
        for (int j = 0; j < chunks; j++)
        {
            ExplorerChunkTerrain* chunk = new ExplorerChunkTerrain(_renderer, start + chunksize * (double) i, start + chunksize * (double) j, chunksize, chunks, water_height);
            _chunks.append(chunk);
            _updateQueue.append(chunk);
        }
    }

    // Add skybox
    for (int orientation = 0; orientation < 5; orientation++)
    {
        ExplorerChunkSky* chunk = new ExplorerChunkSky(_renderer, 500.0, (SkyboxOrientation) orientation);
        _chunks.append(chunk);
        _updateQueue.append(chunk);
    }

    // Start rendering workers
    int nbcore;
    _alive = true;

    nbcore = QThread::idealThreadCount();
    if (nbcore < 1)
    {
        nbcore = 1;
    }

    for (int i = 0; i < nbcore; i++)
    {
        _threads.append(new ChunkMaintenanceThread(this));
    }
    for (int i = 0; i < _threads.count(); i++)
    {
        _threads[i]->start();
    }
}

void WidgetExplorer::stopRendering()
{
    for (int i = 0; i < _threads.count(); i++)
    {
        _threads[i]->askStop();
    }
    _alive = false;
    for (int i = 0; i < _threads.count(); i++)
    {
        _threads[i]->wait();
    }
}

bool _cmpChunks(const BaseExplorerChunk* c1, const BaseExplorerChunk* c2)
{
    return c1->priority > c2->priority;
}

void WidgetExplorer::performChunksMaintenance()
{
    BaseExplorerChunk* chunk;

    _lock_chunks.lock();
    if (_updateQueue.count() > 0)
    {
        chunk = _updateQueue.takeFirst();
        _lock_chunks.unlock();
    }
    else
    {
        _lock_chunks.unlock();
        return;
    }

    if (chunk->maintain())
    {
        if (!_alive)
        {
            return;
        }

        _updated = true;
    }

    _lock_chunks.lock();
    _updateQueue.append(chunk);
    _lock_chunks.unlock();
}

void WidgetExplorer::resetCamera()
{
    _base_camera->copy(_current_camera);
    updateGL();
}

void WidgetExplorer::validateCamera()
{
    _current_camera->copy(_base_camera);
}

void WidgetExplorer::keyPressEvent(QKeyEvent* event)
{
    double factor;

    if (event->modifiers() & Qt::ControlModifier)
    {
        factor = 0.1;
    }
    else if (event->modifiers() & Qt::ShiftModifier)
    {
        factor = 10.0;
    }
    else
    {
        factor = 1.0;
    }
    factor *= 3.0;

    if (event->key() == Qt::Key_Up)
    {
        _current_camera->strafeForward(0.1 * factor);
        updateGL();
    }
    else if (event->key() == Qt::Key_Down)
    {
        _current_camera->strafeForward(-0.1 * factor);
        updateGL();
    }
    else if (event->key() == Qt::Key_Right)
    {
        _current_camera->strafeRight(0.1 * factor);
        updateGL();
    }
    else if (event->key() == Qt::Key_Left)
    {
        _current_camera->strafeRight(-0.1 * factor);
        updateGL();
    }
    else if (event->key() == Qt::Key_PageUp)
    {
        _current_camera->strafeUp(0.1 * factor);
        updateGL();
    }
    else if (event->key() == Qt::Key_PageDown)
    {
        _current_camera->strafeUp(-0.1 * factor);
        updateGL();
    }
    else
    {
        QGLWidget::keyPressEvent(event);
    }
}

void WidgetExplorer::mousePressEvent(QMouseEvent* event)
{
    _last_mouse_x = event->x();
    _last_mouse_y = event->y();

    event->ignore();
}

void WidgetExplorer::mouseMoveEvent(QMouseEvent* event)
{
    double factor;

    if (event->modifiers() & Qt::ControlModifier)
    {
        factor = 0.01;
    }
    else if (event->modifiers() & Qt::ShiftModifier)
    {
        factor = 1.0;
    }
    else
    {
        factor = 0.1;
    }
    factor *= 0.2;

    if (event->buttons() & Qt::LeftButton)
    {
        _current_camera->rotateYaw((double) (event->x() - _last_mouse_x) * factor * 0.1);
        _current_camera->rotatePitch((double) (event->y() - _last_mouse_y) * factor * 0.1);
        updateGL();
        event->accept();
    }
    else if (event->buttons() & Qt::RightButton)
    {
        _current_camera->strafeRight((double) (_last_mouse_x - event->x()) * factor);
        _current_camera->strafeUp((double) (event->y() - _last_mouse_y) * factor);
        updateGL();
        event->accept();
    }
    else
    {
        event->ignore();
    }

    _last_mouse_x = event->x();
    _last_mouse_y = event->y();
}

void WidgetExplorer::wheelEvent(QWheelEvent* event)
{
    double factor;

    if (event->modifiers() & Qt::ControlModifier)
    {
        factor = 0.01;
    }
    else if (event->modifiers() & Qt::ShiftModifier)
    {
        factor = 1.0;
    }
    else
    {
        factor = 0.1;
    }
    factor *= 0.03;

    if (event->orientation() == Qt::Vertical)
    {
        _current_camera->strafeForward((double) event->delta() * factor);
        updateGL();
    }
    event->accept();
}

void WidgetExplorer::timerEvent(QTimerEvent*)
{
    if (!_inited)
    {
        _inited = true;
        startRendering();
    }

    if (_updated)
    {
        _updated = false;
        updateGL();
    }

    for (int i = 0; i < _chunks.count(); i++)
    {
        _chunks[i]->updatePriority(_current_camera);
    }
    _lock_chunks.lock();
    qSort(_updateQueue.begin(), _updateQueue.end(), _cmpChunks);
    _lock_chunks.unlock();
}

void WidgetExplorer::initializeGL()
{
    _opengl_renderer->initialize();
}

void WidgetExplorer::resizeGL(int w, int h)
{
    _current_camera->setRenderSize(w, h);
    _opengl_renderer->resize(w, h);
}

void WidgetExplorer::paintGL()
{
    GLenum error_code;
    QTime start_time;
    double frame_time;
    WaterDefinition* water = _renderer->water->definition;

    // Don't do this at each frame, only on camera change
    _renderer->getScenery()->setCamera(_current_camera);
    _renderer->getScenery()->getCamera(_current_camera);

    start_time = QTime::currentTime();

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    Vector3 camera_location = _current_camera->getLocation();
    Vector3 camera_target = _current_camera->getTarget();
    Vector3 camera_up = _current_camera->getUpVector();
    gluLookAt(camera_location.x, camera_location.y, camera_location.z, camera_target.x, camera_target.y, camera_target.z, camera_up.x, camera_up.y, camera_up.z);

    // Background
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Render water
    double water_height = _renderer->terrain->getWaterHeight(_renderer);
    glDisable(GL_TEXTURE_2D);
    glColor3f(water->material->_rgb.r, water->material->_rgb.g, water->material->_rgb.b);
    glBegin(GL_QUADS);
    glVertex3f(camera_location.x - 500.0, water_height, camera_location.z - 500.0);
    glVertex3f(camera_location.x - 500.0, water_height, camera_location.z + 500.0);
    glVertex3f(camera_location.x + 500.0, water_height, camera_location.z + 500.0);
    glVertex3f(camera_location.x + 500.0, water_height, camera_location.z - 500.0);
    glEnd();

    // Render chunks
    glEnable(GL_TEXTURE_2D);
    for (int i = 0; i < _chunks.count(); i++)
    {
        glColor3f(1.0, 1.0, 1.0);
        _chunks[i]->render(this);
    }

    frame_time = 0.001 * (double) start_time.msecsTo(QTime::currentTime());

    _average_frame_time = _average_frame_time * 0.8 + frame_time * 0.2;
    //printf("%d %f\n", quality, average_frame_time);

    if (_average_frame_time > 0.1 && _quality > 1)
    {
        _quality--;
    }
    if (_average_frame_time < 0.04 && _quality < 10)
    {
        _quality++;
    }

    // Messages
    if (!_inited)
    {
        glColor3f(0.0, 0.0, 0.0);
        renderText(6, height() - 10, tr("Please wait while loading scene..."));
        glColor3f(1.0, 1.0, 1.0);
        renderText(5, height() - 9, tr("Please wait while loading scene..."));
    }

    while ((error_code = glGetError()) != GL_NO_ERROR)
    {
        qDebug("[OpenGL] ERROR : %s", (const char*)gluErrorString(error_code));
    }
}
<|endoftext|>