<commit_before>#include <string>

/*
public class TennisGame4 implements TennisGame {

    int serverScore;
    int receiverScore;
    String server;
    String receiver;

    public TennisGame4(String player1, String player2) {
        this.server = player1;
        this.receiver = player2;
    }

    @java.lang.Override
    public void wonPoint(String playerName) {
        if (server.equals(playerName))
            this.serverScore += 1;
        else
            this.receiverScore += 1;
    }

    @java.lang.Override
    public String getScore() {
        TennisResult result = new Deuce(
                this, new GameServer(
                        this, new GameReceiver(
                                this, new AdvantageServer(
                                        this, new AdvantageReceiver(
                                                this, new DefaultResult(this)))))).getResult();
        return result.format();
    }

    boolean receiverHasAdvantage() {
        return receiverScore >= 4 && (receiverScore - serverScore) == 1;
    }

    boolean serverHasAdvantage() {
        return serverScore >= 4 && (serverScore - receiverScore) == 1;
    }

    boolean receiverHasWon() {
        return receiverScore >= 4 && (receiverScore - serverScore) >= 2;
    }

    boolean serverHasWon() {
        return serverScore >= 4 && (serverScore - receiverScore) >= 2;
    }

    boolean isDeuce() {
        return serverScore >= 3 && receiverScore >= 3 && (serverScore == receiverScore);
    }
}

class TennisResult {
    String serverScore;
    String receiverScore;

    TennisResult(String serverScore, String receiverScore) {
        this.serverScore = serverScore;
        this.receiverScore = receiverScore;
    }

    String format() {
        if ("".equals(this.receiverScore))
            return this.serverScore;
        if (serverScore.equals(receiverScore))
            return serverScore + "-All";
        return this.serverScore + "-" + this.receiverScore;
    }
}

interface ResultProvider {
    TennisResult getResult();
}

class Deuce implements ResultProvider {
    private final TennisGame4 game;
    private final ResultProvider nextResult;

    public Deuce(TennisGame4 game, ResultProvider nextResult) {
        this.game = game;
        this.nextResult = nextResult;
    }

    @Override
    public TennisResult getResult() {
        if (game.isDeuce())
            return new TennisResult("Deuce", "");
        return this.nextResult.getResult();
    }
}

class GameServer implements ResultProvider {
    private final TennisGame4 game;
    private final ResultProvider nextResult;

    public GameServer(TennisGame4 game, ResultProvider nextResult) {
        this.game = game;
        this.nextResult = nextResult;
    }

    @Override
    public TennisResult getResult() {
        if (game.serverHasWon())
            return new TennisResult("Win for " + game.server, "");
        return this.nextResult.getResult();
    }
}

class GameReceiver implements ResultProvider {
    private final TennisGame4 game;
    private final ResultProvider nextResult;

    public GameReceiver(TennisGame4 game, ResultProvider nextResult) {
        this.game = game;
        this.nextResult = nextResult;
    }

    @Override
    public TennisResult getResult() {
        if (game.receiverHasWon())
            return new TennisResult("Win for " + game.receiver, "");
        return this.nextResult.getResult();
    }t
}

class AdvantageServer implements ResultProvider {
    private final TennisGame4 game;
    private final ResultProvider nextResult;

    public AdvantageServer(TennisGame4 game, ResultProvider nextResult) {
        this.game = game;
        this.nextResult = nextResult;
    }

    @Override
    public TennisResult getResult() {
        if (game.serverHasAdvantage())
            return new TennisResult("Advantage " + game.server, "");
        return this.nextResult.getResult();
    }
}

class AdvantageReceiver implements ResultProvider {

    private final TennisGame4 game;
    private final ResultProvider nextResult;

    public AdvantageReceiver(TennisGame4 game, ResultProvider nextResult) {
        this.game = game;
        this.nextResult = nextResult;
    }

    @Override
    public TennisResult getResult() {
        if (game.receiverHasAdvantage())
            return new TennisResult("Advantage " + game.receiver, "");
        return this.nextResult.getResult();
    }
}

class DefaultResult implements ResultProvider {

    private static final String[] scores = {"Love", "Fifteen", "Thirty", "Forty"};

    private final TennisGame4 game;

    public DefaultResult(TennisGame4 game) {
        this.game = game;
    }

    @Override
    public TennisResult getResult() {
        return new TennisResult(scores[game.serverScore], scores[game.receiverScore]);
    }
}
 */

class TennisResult {
    std::string serverScore;
    std::string receiverScore;

    TennisResult(std::string serverScore, std::string receiverScore) {
        this->serverScore = serverScore;
        this->receiverScore = receiverScore;
    }

    std::string format() {
        if ("" == this->receiverScore)
            return this->serverScore;
        if (serverScore == this->receiverScore)
            return serverScore + "-All";
        return this->serverScore + "-" + this->receiverScore;
    }
};

class ResultProvider {
    virtual ~ResultProvider() {}
    virtual TennisResult getResult() = 0;
};

const std::string tennis_score(int p1, int p2) {
    std::string s;
    std::string p1N = "player1";
    std::string p2N = "player2";
    if ((p1 < 4 && p2 < 4) && (p1 + p2 < 6)) {
        std::string p[4] = {"Love", "Fifteen", "Thirty", "Forty"};
        s = p[p1];
        return (p1 == p2) ? s + "-All" : s + "-" + p[p2];
    } else {
        if (p1 == p2)
            return "Deuce";
        s = p1 > p2 ? p1N : p2N;
        return ((p1-p2)*(p1-p2) == 1) ? "Advantage " + s : "Win for " + s;
    }
}<commit_msg>Add helpful w.i.p comments<commit_after>#include <string>

/*
public class TennisGame4 implements TennisGame {

    int serverScore;
    int receiverScore;
    String server;
    String receiver;

    public TennisGame4(String player1, String player2) {
        this.server = player1;
        this.receiver = player2;
    }

    @java.lang.Override
    public void wonPoint(String playerName) {
        if (server.equals(playerName))
            this.serverScore += 1;
        else
            this.receiverScore += 1;
    }

    @java.lang.Override
    public String getScore() {
        TennisResult result = new Deuce(
                this, new GameServer(
                        this, new GameReceiver(
                                this, new AdvantageServer(
                                        this, new AdvantageReceiver(
                                                this, new DefaultResult(this)))))).getResult();
        return result.format();
    }

    boolean receiverHasAdvantage() {
        return receiverScore >= 4 && (receiverScore - serverScore) == 1;
    }

    boolean serverHasAdvantage() {
        return serverScore >= 4 && (serverScore - receiverScore) == 1;
    }

    boolean receiverHasWon() {
        return receiverScore >= 4 && (receiverScore - serverScore) >= 2;
    }

    boolean serverHasWon() {
        return serverScore >= 4 && (serverScore - receiverScore) >= 2;
    }

    boolean isDeuce() {
        return serverScore >= 3 && receiverScore >= 3 && (serverScore == receiverScore);
    }
}

class TennisResult {
    String serverScore;
    String receiverScore;

    TennisResult(String serverScore, String receiverScore) {
        this.serverScore = serverScore;
        this.receiverScore = receiverScore;
    }

    String format() {
        if ("".equals(this.receiverScore))
            return this.serverScore;
        if (serverScore.equals(receiverScore))
            return serverScore + "-All";
        return this.serverScore + "-" + this.receiverScore;
    }
}

interface ResultProvider {
    TennisResult getResult();
}

class Deuce implements ResultProvider {
    private final TennisGame4 game;
    private final ResultProvider nextResult;

    public Deuce(TennisGame4 game, ResultProvider nextResult) {
        this.game = game;
        this.nextResult = nextResult;
    }

    @Override
    public TennisResult getResult() {
        if (game.isDeuce())
            return new TennisResult("Deuce", "");
        return this.nextResult.getResult();
    }
}

class GameServer implements ResultProvider {
    private final TennisGame4 game;
    private final ResultProvider nextResult;

    public GameServer(TennisGame4 game, ResultProvider nextResult) {
        this.game = game;
        this.nextResult = nextResult;
    }

    @Override
    public TennisResult getResult() {
        if (game.serverHasWon())
            return new TennisResult("Win for " + game.server, "");
        return this.nextResult.getResult();
    }
}

class GameReceiver implements ResultProvider {
    private final TennisGame4 game;
    private final ResultProvider nextResult;

    public GameReceiver(TennisGame4 game, ResultProvider nextResult) {
        this.game = game;
        this.nextResult = nextResult;
    }

    @Override
    public TennisResult getResult() {
        if (game.receiverHasWon())
            return new TennisResult("Win for " + game.receiver, "");
        return this.nextResult.getResult();
    }t
}

class AdvantageServer implements ResultProvider {
    private final TennisGame4 game;
    private final ResultProvider nextResult;

    public AdvantageServer(TennisGame4 game, ResultProvider nextResult) {
        this.game = game;
        this.nextResult = nextResult;
    }

    @Override
    public TennisResult getResult() {
        if (game.serverHasAdvantage())
            return new TennisResult("Advantage " + game.server, "");
        return this.nextResult.getResult();
    }
}

class AdvantageReceiver implements ResultProvider {

    private final TennisGame4 game;
    private final ResultProvider nextResult;

    public AdvantageReceiver(TennisGame4 game, ResultProvider nextResult) {
        this.game = game;
        this.nextResult = nextResult;
    }

    @Override
    public TennisResult getResult() {
        if (game.receiverHasAdvantage())
            return new TennisResult("Advantage " + game.receiver, "");
        return this.nextResult.getResult();
    }
}

class DefaultResult implements ResultProvider {

    private static final String[] scores = {"Love", "Fifteen", "Thirty", "Forty"};

    private final TennisGame4 game;

    public DefaultResult(TennisGame4 game) {
        this.game = game;
    }

    @Override
    public TennisResult getResult() {
        return new TennisResult(scores[game.serverScore], scores[game.receiverScore]);
    }
}
 */

class TennisResult {
    std::string serverScore;
    std::string receiverScore;

    TennisResult(std::string serverScore, std::string receiverScore) {
        this->serverScore = serverScore;
        this->receiverScore = receiverScore;
    }

    std::string format() {
        if ("" == this->receiverScore)
            return this->serverScore;
        if (serverScore == this->receiverScore)
            return serverScore + "-All";
        return this->serverScore + "-" + this->receiverScore;
    }
};

class ResultProvider {
    virtual ~ResultProvider() {}
    virtual TennisResult getResult() = 0;
};

/*
public class TennisGame4 implements TennisGame {
##class TennisResult {
##interface ResultProvider {
class Deuce implements ResultProvider {
class GameServer implements ResultProvider {
class GameReceiver implements ResultProvider {
class AdvantageServer implements ResultProvider {
class AdvantageReceiver implements ResultProvider {
class DefaultResult implements ResultProvider {
 */

// tennis3 function below (TODO: re-implement using class mess above!)
/* relevant inspiration from Java Unit Test
    public void checkAllScores(TennisGame game) {
        int highestScore = Math.max(this.player1Score, this.player2Score);
        for (int i = 0; i < highestScore; i++) {
            if (i < this.player1Score)
                game.wonPoint("player1");
            if (i < this.player2Score)
                game.wonPoint("player2");
        }
        assertEquals(this.expectedScore, game.getScore());
    }
*/
const std::string tennis_score(int p1, int p2) {
    std::string s;
    std::string p1N = "player1";
    std::string p2N = "player2";
    if ((p1 < 4 && p2 < 4) && (p1 + p2 < 6)) {
        std::string p[4] = {"Love", "Fifteen", "Thirty", "Forty"};
        s = p[p1];
        return (p1 == p2) ? s + "-All" : s + "-" + p[p2];
    } else {
        if (p1 == p2)
            return "Deuce";
        s = p1 > p2 ? p1N : p2N;
        return ((p1-p2)*(p1-p2) == 1) ? "Advantage " + s : "Win for " + s;
    }
}<|endoftext|>


<commit_before>/* Copyright 2015 Samsung Electronics Co., LTD
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "glm/glm.hpp"
#include "glm/gtc/type_ptr.hpp"
#include "shaders/shader.h"
#include "shader_data.h"

namespace gvr {
/**
 * Constructs a bnse material.
 * The material contains a UniformBlock describing the possible uniforms
 * that can be used by this material. It also maintains the list of
 * possible textures in the order specified by the descriptor.
 * All materials which use the same shader will have the same ordering
 * of uniforms and textures in their descriptors.
 * @param uniform_desc  string describing uniforms used by this material
 * @param texture_desc  string describing textures used by this material
 */
    ShaderData::ShaderData(const char* texture_desc) :
            mNativeShader(0),
            mTextureDesc(texture_desc),
            mLock()
    {
        DataDescriptor texdesc(texture_desc);
        texdesc.forEach([this](const char* name, const char* type, int size) mutable
        {
            mTextureNames.push_back(name);
            mTextures.push_back(nullptr);
        });
    }

    Texture* ShaderData::getTexture(const char* key) const
    {
        for (auto it = mTextureNames.begin(); it < mTextureNames.end(); ++it)
        {
            if (*it == key)
            {
                return mTextures[it - mTextureNames.begin()];
            }
        }
        return NULL;
    }

    void ShaderData::setTexture(const char* key, Texture* texture)
    {
        std::lock_guard<std::mutex> lock(mLock);
        for (auto it = mTextureNames.begin(); it < mTextureNames.end(); ++it)
        {
            const std::string& temp = *it;
            if (temp.compare(key) == 0)
            {
                int i = it - mTextureNames.begin();
                Texture* oldtex = mTextures[i];
                dirty(oldtex ? MOD_TEXTURE : NEW_TEXTURE);
                mTextures[i] = texture;
                return;
            }
        }
    }

    /**
     * Visits each texture in the material and calls the given function.
     */
    void ShaderData::forEachTexture(std::function< void(const char* texname, Texture* tex) > func) const
    {
        std::lock_guard<std::mutex> lock(mLock);
        for (int i = 0; i < mTextureNames.size(); ++i)
        {
            Texture* tex = mTextures[i];
            const std::string& name = mTextureNames[i];
            func(name.c_str(), tex);
        }
    }

    std::string ShaderData::makeShaderLayout()
    {
        return uniforms().makeShaderLayout();
    }

    int ShaderData::getByteSize(const char* name) const
    {
        return uniforms().getByteSize(name);
    }

    const char* ShaderData::getUniformDescriptor() const
    {
        return uniforms().getDescriptor();
    }

    const char* ShaderData::getTextureDescriptor() const
    {
        return mTextureDesc.c_str();
    }

    bool ShaderData::getFloat(const char* name, float& v) const
    {
        return uniforms().getFloat(name, v);
    }

    bool   ShaderData::getInt(const char* name, int& v) const
    {
        return uniforms().getInt(name, v);
    }

    bool  ShaderData::setInt(const char* name, int val)
    {
        std::lock_guard<std::mutex> lock(mLock);
        dirty(MAT_DATA);
        return uniforms().setInt(name, val);
    }

    bool  ShaderData::setFloat(const char* name, float val)
    {
        std::lock_guard<std::mutex> lock(mLock);
        dirty(MAT_DATA);
        return uniforms().setFloat(name, val);
    }

    bool  ShaderData::setIntVec(const char* name, const int* val, int n)
    {
        std::lock_guard<std::mutex> lock(mLock);
        dirty(MAT_DATA);
        return uniforms().setIntVec(name, val, n);
    }

    bool  ShaderData::setFloatVec(const char* name, const float* val, int n)
    {
        std::lock_guard<std::mutex> lock(mLock);
        dirty(MAT_DATA);
        return uniforms().setFloatVec(name, val, n);
    }

    bool  ShaderData::getFloatVec(const char* name, float* val, int n)
    {
        return uniforms().getFloatVec(name, val, n);
    }

    bool  ShaderData::getIntVec(const char* name, int* val, int n)
    {
        return uniforms().getIntVec(name, val, n);
    }

    bool  ShaderData::setVec2(const char* name, const glm::vec2& v)
    {
        std::lock_guard<std::mutex> lock(mLock);
        return uniforms().setVec2(name, v);
    }

    bool  ShaderData::setVec3(const char* name, const glm::vec3& v)
    {
        std::lock_guard<std::mutex> lock(mLock);
        return uniforms().setVec3(name, v);
    }

    bool  ShaderData::setVec4(const char* name, const glm::vec4& v)
    {
        std::lock_guard<std::mutex> lock(mLock);
        return uniforms().setVec4(name, v);
    }

    bool  ShaderData::setMat4(const char* name, const glm::mat4& m)
    {
        std::lock_guard<std::mutex> lock(mLock);
        return uniforms().setMat4(name, m);
    }

    void ShaderData::add_dirty_flag(const std::shared_ptr<u_short>& dirty_flag)
    {
        mDirtyFlags.insert(dirty_flag);
    }

    void ShaderData::add_dirty_flags(const std::unordered_set<std::shared_ptr<u_short>>& dirty_flags)
    {
        mDirtyFlags.insert(dirty_flags.begin(), dirty_flags.end());
    }

    void ShaderData::dirty(DIRTY_BITS bit)
    {
        dirtyImpl(mDirtyFlags,bit);
    }

    bool ShaderData::hasTexture(const char* key) const
    {
        for (auto it = mTextureNames.begin(); it < mTextureNames.end(); ++it)
        {
            if (*it == key)
            {
                return true;
            }
        }
        return false;
    }

    bool ShaderData::hasUniform(const char* key) const
    {
        return (uniforms().getByteSize(key) > 0);
    }

    /**
     * Updates the values of the uniforms and textures
     * by copying the relevant data from the CPU to the GPU.
     * This function operates independently of the shader,
     * so it cannot tell if a texture the shader requires
     * is missing.
     * @param renderer
     * @return 1 = success, -1 texture not ready, 0 uniforms failed to load
     */
    int ShaderData::updateGPU(Renderer* renderer)
    {
        std::lock_guard<std::mutex> lock(mLock);
        for (auto it = mTextures.begin(); it != mTextures.end(); ++it)
        {
            Texture *tex = *it;

            if (tex != NULL)
            {
                bool ready = tex->isReady();
                if (Shader::LOG_SHADER)
                {
                    const std::string& name = mTextureNames[it - mTextures.begin()];
                    LOGV("ShaderData::updateGPU %s is %s", name.c_str(),
                         ready ? "ready" : "not ready");
                }
                if (!ready)
                {
                    return -1;
                }
            }
        }
        return 1;
    }

}

<commit_msg>fix screen shot shader, texturing bug<commit_after>/* Copyright 2015 Samsung Electronics Co., LTD
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "glm/glm.hpp"
#include "glm/gtc/type_ptr.hpp"
#include "shaders/shader.h"
#include "shader_data.h"

namespace gvr {
/**
 * Constructs a bnse material.
 * The material contains a UniformBlock describing the possible uniforms
 * that can be used by this material. It also maintains the list of
 * possible textures in the order specified by the descriptor.
 * All materials which use the same shader will have the same ordering
 * of uniforms and textures in their descriptors.
 * @param uniform_desc  string describing uniforms used by this material
 * @param texture_desc  string describing textures used by this material
 */
    ShaderData::ShaderData(const char* texture_desc) :
            mNativeShader(0),
            mTextureDesc(texture_desc),
            mLock()
    {
        DataDescriptor texdesc(texture_desc);
        texdesc.forEach([this](const char* name, const char* type, int size) mutable
        {
            mTextureNames.push_back(name);
            mTextures.push_back(nullptr);
        });
    }

    Texture* ShaderData::getTexture(const char* key) const
    {
        for (auto it = mTextureNames.begin(); it < mTextureNames.end(); ++it)
        {
            if (*it == key)
            {
                return mTextures[it - mTextureNames.begin()];
            }
        }
        return NULL;
    }

    void ShaderData::setTexture(const char* key, Texture* texture)
    {
        std::lock_guard<std::mutex> lock(mLock);
        for (auto it = mTextureNames.begin(); it < mTextureNames.end(); ++it)
        {
            const std::string& temp = *it;
            if (temp.compare(key) == 0)
            {
                int i = it - mTextureNames.begin();
                Texture* oldtex = mTextures[i];
                dirty(oldtex ? MOD_TEXTURE : NEW_TEXTURE);
                mTextures[i] = texture;
                return;
            }
        }
    }

    /**
     * Visits each texture in the material and calls the given function.
     */
    void ShaderData::forEachTexture(std::function< void(const char* texname, Texture* tex) > func) const
    {
        std::lock_guard<std::mutex> lock(mLock);
        for (int i = 0; i < mTextureNames.size(); ++i)
        {
            Texture* tex = mTextures[i];
            const std::string& name = mTextureNames[i];
            func(name.c_str(), tex);
        }
    }

    std::string ShaderData::makeShaderLayout()
    {
        return uniforms().makeShaderLayout();
    }

    int ShaderData::getByteSize(const char* name) const
    {
        return uniforms().getByteSize(name);
    }

    const char* ShaderData::getUniformDescriptor() const
    {
        return uniforms().getDescriptor();
    }

    const char* ShaderData::getTextureDescriptor() const
    {
        return mTextureDesc.c_str();
    }

    bool ShaderData::getFloat(const char* name, float& v) const
    {
        return uniforms().getFloat(name, v);
    }

    bool   ShaderData::getInt(const char* name, int& v) const
    {
        return uniforms().getInt(name, v);
    }

    bool  ShaderData::setInt(const char* name, int val)
    {
        std::lock_guard<std::mutex> lock(mLock);
        dirty(MAT_DATA);
        return uniforms().setInt(name, val);
    }

    bool  ShaderData::setFloat(const char* name, float val)
    {
        std::lock_guard<std::mutex> lock(mLock);
        dirty(MAT_DATA);
        return uniforms().setFloat(name, val);
    }

    bool  ShaderData::setIntVec(const char* name, const int* val, int n)
    {
        std::lock_guard<std::mutex> lock(mLock);
        dirty(MAT_DATA);
        return uniforms().setIntVec(name, val, n);
    }

    bool  ShaderData::setFloatVec(const char* name, const float* val, int n)
    {
        std::lock_guard<std::mutex> lock(mLock);
        dirty(MAT_DATA);
        return uniforms().setFloatVec(name, val, n);
    }

    bool  ShaderData::getFloatVec(const char* name, float* val, int n)
    {
        return uniforms().getFloatVec(name, val, n);
    }

    bool  ShaderData::getIntVec(const char* name, int* val, int n)
    {
        return uniforms().getIntVec(name, val, n);
    }

    bool  ShaderData::setVec2(const char* name, const glm::vec2& v)
    {
        std::lock_guard<std::mutex> lock(mLock);
        return uniforms().setVec2(name, v);
    }

    bool  ShaderData::setVec3(const char* name, const glm::vec3& v)
    {
        std::lock_guard<std::mutex> lock(mLock);
        return uniforms().setVec3(name, v);
    }

    bool  ShaderData::setVec4(const char* name, const glm::vec4& v)
    {
        std::lock_guard<std::mutex> lock(mLock);
        return uniforms().setVec4(name, v);
    }

    bool  ShaderData::setMat4(const char* name, const glm::mat4& m)
    {
        std::lock_guard<std::mutex> lock(mLock);
        return uniforms().setMat4(name, m);
    }

    void ShaderData::add_dirty_flag(const std::shared_ptr<u_short>& dirty_flag)
    {
        mDirtyFlags.insert(dirty_flag);
    }

    void ShaderData::add_dirty_flags(const std::unordered_set<std::shared_ptr<u_short>>& dirty_flags)
    {
        mDirtyFlags.insert(dirty_flags.begin(), dirty_flags.end());
    }

    void ShaderData::dirty(DIRTY_BITS bit)
    {
        dirtyImpl(mDirtyFlags,bit);
    }

    bool ShaderData::hasTexture(const char* key) const
    {
        for (auto it = mTextureNames.begin(); it < mTextureNames.end(); ++it)
        {
            if (*it == key)
            {
                return true;
            }
        }
        return false;
    }

    bool ShaderData::hasUniform(const char* key) const
    {
        return (uniforms().getByteSize(key) > 0);
    }

    /**
     * Updates the values of the uniforms and textures
     * by copying the relevant data from the CPU to the GPU.
     * This function operates independently of the shader,
     * so it cannot tell if a texture the shader requires
     * is missing.
     * @param renderer
     * @return 1 = success, -1 texture not ready, 0 uniforms failed to load
     */
    int ShaderData::updateGPU(Renderer* renderer)
    {
        std::lock_guard<std::mutex> lock(mLock);
        for (auto it = mTextures.begin(); it != mTextures.end(); ++it)
        {
            Texture *tex = *it;

            if (tex != NULL)
            {
                bool ready = tex->isReady();
                if (Shader::LOG_SHADER)
                {
                    const std::string& name = mTextureNames[it - mTextures.begin()];
                    LOGV("ShaderData::updateGPU %s is %s", name.c_str(),
                         ready ? "ready" : "not ready");
                }
                if (!ready)
                {
                    return -1;
                }
            }
        }
        return (uniforms().updateGPU(renderer) ? 1 : 0);
    }

}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2009 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "WebImage.h"

#include "WebData.h"
#include "WebSize.h"

#include "Image.h"
#include "ImageSource.h"
#include "NativeImageSkia.h"
#include "SharedBuffer.h"
#include <wtf/OwnPtr.h>
#include <wtf/PassRefPtr.h>

using namespace WebCore;

namespace WebKit {

WebImage WebImage::fromData(const WebData& data, const WebSize& desiredSize)
{
    ImageSource source;
    source.setData(PassRefPtr<SharedBuffer>(data).get(), true);
    if (!source.isSizeAvailable())
        return WebImage();

    // Frames are arranged by decreasing size, then decreasing bit depth.
    // Pick the frame closest to |desiredSize|'s area without being smaller,
    // which has the highest bit depth.
    const size_t frameCount = source.frameCount();
    size_t index;
    int frameAreaAtIndex;
    for (size_t i = 0; i < frameCount; ++i) {
        const IntSize frameSize = source.frameSizeAtIndex(i);
        if (WebSize(frameSize) == desiredSize) {
            index = i;
            break;  // Perfect match.
        }

        const int frameArea = frameSize.width() * frameSize.height();
        if (frameArea < (desiredSize.width * desiredSize.height))
            break;  // No more frames that are large enough.

        if ((i == 0) || (frameArea < frameAreaAtIndex)) {
            index = i;  // Closer to desired area than previous best match.
            frameAreaAtIndex = frameArea;
        }
    }

    OwnPtr<NativeImageSkia> frame(source.createFrameAtIndex(index));
    if (!frame.get())
        return WebImage();

    return WebImage(*frame);
}

void WebImage::reset()
{
    m_bitmap.reset();
}

void WebImage::assign(const WebImage& image)
{
    m_bitmap = image.m_bitmap;
}

bool WebImage::isNull() const
{
    return m_bitmap.isNull();
}

WebSize WebImage::size() const
{
    return WebSize(m_bitmap.width(), m_bitmap.height());
}

WebImage::WebImage(const PassRefPtr<Image>& image)
{
    operator=(image);
}

WebImage& WebImage::operator=(const PassRefPtr<Image>& image)
{
    NativeImagePtr p;
    if (image.get() && (p = image->nativeImageForCurrentFrame()))
        assign(*p);
    else
        reset();
    return *this;
}

} // namespace WebKit
<commit_msg>Fix possible uninitialized variable if all frames in the .ico are smaller than the desired size.<commit_after>/*
 * Copyright (C) 2009 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "WebImage.h"

#include "WebData.h"
#include "WebSize.h"

#include "Image.h"
#include "ImageSource.h"
#include "NativeImageSkia.h"
#include "SharedBuffer.h"
#include <wtf/OwnPtr.h>
#include <wtf/PassRefPtr.h>

using namespace WebCore;

namespace WebKit {

WebImage WebImage::fromData(const WebData& data, const WebSize& desiredSize)
{
    ImageSource source;
    source.setData(PassRefPtr<SharedBuffer>(data).get(), true);
    if (!source.isSizeAvailable())
        return WebImage();

    // Frames are arranged by decreasing size, then decreasing bit depth.
    // Pick the frame closest to |desiredSize|'s area without being smaller,
    // which has the highest bit depth.
    const size_t frameCount = source.frameCount();
    size_t index = 0;  // Default to first frame if none are large enough.
    int frameAreaAtIndex;
    for (size_t i = 0; i < frameCount; ++i) {
        const IntSize frameSize = source.frameSizeAtIndex(i);
        if (WebSize(frameSize) == desiredSize) {
            index = i;
            break;  // Perfect match.
        }

        const int frameArea = frameSize.width() * frameSize.height();
        if (frameArea < (desiredSize.width * desiredSize.height))
            break;  // No more frames that are large enough.

        if ((i == 0) || (frameArea < frameAreaAtIndex)) {
            index = i;  // Closer to desired area than previous best match.
            frameAreaAtIndex = frameArea;
        }
    }

    OwnPtr<NativeImageSkia> frame(source.createFrameAtIndex(index));
    if (!frame.get())
        return WebImage();

    return WebImage(*frame);
}

void WebImage::reset()
{
    m_bitmap.reset();
}

void WebImage::assign(const WebImage& image)
{
    m_bitmap = image.m_bitmap;
}

bool WebImage::isNull() const
{
    return m_bitmap.isNull();
}

WebSize WebImage::size() const
{
    return WebSize(m_bitmap.width(), m_bitmap.height());
}

WebImage::WebImage(const PassRefPtr<Image>& image)
{
    operator=(image);
}

WebImage& WebImage::operator=(const PassRefPtr<Image>& image)
{
    NativeImagePtr p;
    if (image.get() && (p = image->nativeImageForCurrentFrame()))
        assign(*p);
    else
        reset();
    return *this;
}

} // namespace WebKit
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "config.h"

#include "base/compiler_specific.h"

#include "KeyboardCodes.h"
#include "StringImpl.h"  // This is so that the KJS build works

MSVC_PUSH_WARNING_LEVEL(0);
#include "PlatformKeyboardEvent.h"
#include "PlatformMouseEvent.h"
#include "PlatformWheelEvent.h"
#include "Widget.h"
MSVC_POP_WARNING();

#undef LOG
#include "base/gfx/point.h"
#include "base/logging.h"
#include "webkit/glue/event_conversion.h"
#include "webkit/glue/webinputevent.h"
#include "webkit/glue/webkit_glue.h"

using namespace WebCore;

// MakePlatformMouseEvent -----------------------------------------------------

int MakePlatformMouseEvent::last_click_count_ = 0;
uint32 MakePlatformMouseEvent::last_click_time_ = 0;

MakePlatformMouseEvent::MakePlatformMouseEvent(Widget* widget,
                                               const WebMouseEvent& e) {
  // TODO(mpcomplete): widget is always toplevel, unless it's a popup.  We
  // may be able to get rid of this once we abstract popups into a WebKit API.
  m_position = widget->convertFromContainingWindow(IntPoint(e.x, e.y));
  m_globalPosition = IntPoint(e.global_x, e.global_y);
  m_button = static_cast<MouseButton>(e.button);
  m_shiftKey = (e.modifiers & WebInputEvent::SHIFT_KEY) != 0;
  m_ctrlKey = (e.modifiers & WebInputEvent::CTRL_KEY) != 0;
  m_altKey = (e.modifiers & WebInputEvent::ALT_KEY) != 0;
  m_metaKey = (e.modifiers & WebInputEvent::META_KEY) != 0;
  m_modifierFlags = e.modifiers;
  m_timestamp = e.timestamp_sec;

  // This differs slightly from the WebKit code in WebKit/win/WebView.cpp where
  // their original code looks buggy.
  static IntPoint last_click_position;
  static MouseButton last_click_button = LeftButton;

  const uint32 current_time = static_cast<uint32>(m_timestamp * 1000);
#if defined(OS_WIN)
  const bool cancel_previous_click =
      (abs(last_click_position.x() - m_position.x()) >
       (GetSystemMetrics(SM_CXDOUBLECLK) / 2)) ||
      (abs(last_click_position.y() - m_position.y()) >
       (GetSystemMetrics(SM_CYDOUBLECLK) / 2)) ||
      ((current_time - last_click_time_) > GetDoubleClickTime());
#elif defined(OS_MACOSX) || defined(OS_LINUX)
  const bool cancel_previous_click = false;
#endif

  switch (e.type) {
    case WebInputEvent::MOUSE_MOVE:
    case WebInputEvent::MOUSE_LEAVE:  // synthesize a move event
      if (cancel_previous_click) {
        last_click_count_ = 0;
        last_click_position = IntPoint();
        last_click_time_ = 0;
      }
      m_clickCount = last_click_count_;
      m_eventType = MouseEventMoved;
      break;

  // TODO(port): make these platform agnostic when we restructure this code.
#if defined(OS_LINUX) || defined(OS_MACOSX)
    case WebInputEvent::MOUSE_DOUBLE_CLICK:
      ++m_clickCount;
      // fall through
    case WebInputEvent::MOUSE_DOWN:
      ++m_clickCount;
      last_click_time_ = current_time;
      last_click_button = m_button;
      m_eventType = MouseEventPressed;
      break;
#else
    case WebInputEvent::MOUSE_DOWN:
    case WebInputEvent::MOUSE_DOUBLE_CLICK:
      if (!cancel_previous_click && (m_button == last_click_button)) {
        ++last_click_count_;
      } else {
        last_click_count_ = 1;
        last_click_position = m_position;
      }
      last_click_time_ = current_time;
      last_click_button = m_button;
      m_clickCount = last_click_count_;
      m_eventType = MouseEventPressed;
      break;
#endif

    case WebInputEvent::MOUSE_UP:
      m_clickCount = last_click_count_;
      m_eventType = MouseEventReleased;
      break;

    default:
      NOTREACHED() << "unexpected mouse event type";
  }

  if (webkit_glue::IsLayoutTestMode()) {
    m_clickCount = e.layout_test_click_count;
  }
}

// MakePlatformWheelEvent -----------------------------------------------------

MakePlatformWheelEvent::MakePlatformWheelEvent(Widget* widget,
                                               const WebMouseWheelEvent& e) {
  m_position = widget->convertFromContainingWindow(IntPoint(e.x, e.y));
  m_globalPosition = IntPoint(e.global_x, e.global_y);
  m_deltaX = static_cast<float>(e.delta_x);
  m_deltaY = static_cast<float>(e.delta_y);
  m_isAccepted = false;
  m_granularity = ScrollByLineWheelEvent;
  m_shiftKey = (e.modifiers & WebInputEvent::SHIFT_KEY) != 0;
  m_ctrlKey = (e.modifiers & WebInputEvent::CTRL_KEY) != 0;
  m_altKey = (e.modifiers & WebInputEvent::ALT_KEY) != 0;
  m_metaKey = (e.modifiers & WebInputEvent::META_KEY) != 0;
}

// MakePlatformKeyboardEvent --------------------------------------------------

static inline const PlatformKeyboardEvent::Type ToPlatformKeyboardEventType(
    WebInputEvent::Type type) {
  switch (type) {
    case WebInputEvent::KEY_UP:
      return PlatformKeyboardEvent::KeyUp;
    case WebInputEvent::KEY_DOWN:
      return PlatformKeyboardEvent::KeyDown;
    case WebInputEvent::CHAR:
      return PlatformKeyboardEvent::Char;
    default:
      ASSERT_NOT_REACHED();
  }
  return PlatformKeyboardEvent::KeyDown;
}

static inline String ToSingleCharacterString(UChar c) {
  return String(&c, 1);
}

static String GetKeyIdentifierForWindowsKeyCode(unsigned short keyCode) {
  switch (keyCode) {
    case VKEY_MENU:
      return "Alt";
    case VKEY_CONTROL:
      return "Control";
    case VKEY_SHIFT:
      return "Shift";
    case VKEY_CAPITAL:
      return "CapsLock";
    case VKEY_LWIN:
    case VKEY_RWIN:
      return "Win";
    case VKEY_CLEAR:
      return "Clear";
    case VKEY_DOWN:
      return "Down";
    // "End"
    case VKEY_END:
      return "End";
    // "Enter"
    case VKEY_RETURN:
      return "Enter";
    case VKEY_EXECUTE:
      return "Execute";
    case VKEY_F1:
      return "F1";
    case VKEY_F2:
      return "F2";
    case VKEY_F3:
      return "F3";
    case VKEY_F4:
      return "F4";
    case VKEY_F5:
      return "F5";
    case VKEY_F6:
      return "F6";
    case VKEY_F7:
      return "F7";
    case VKEY_F8:
      return "F8";
    case VKEY_F9:
      return "F9";
    case VKEY_F10:
      return "F11";
    case VKEY_F12:
      return "F12";
    case VKEY_F13:
      return "F13";
    case VKEY_F14:
      return "F14";
    case VKEY_F15:
      return "F15";
    case VKEY_F16:
      return "F16";
    case VKEY_F17:
      return "F17";
    case VKEY_F18:
      return "F18";
    case VKEY_F19:
      return "F19";
    case VKEY_F20:
      return "F20";
    case VKEY_F21:
      return "F21";
    case VKEY_F22:
      return "F22";
    case VKEY_F23:
      return "F23";
    case VKEY_F24:
      return "F24";
    case VKEY_HELP:
      return "Help";
    case VKEY_HOME:
      return "Home";
    case VKEY_INSERT:
      return "Insert";
    case VKEY_LEFT:
      return "Left";
    case VKEY_NEXT:
      return "PageDown";
    case VKEY_PRIOR:
      return "PageUp";
    case VKEY_PAUSE:
      return "Pause";
    case VKEY_SNAPSHOT:
      return "PrintScreen";
    case VKEY_RIGHT:
      return "Right";
    case VKEY_SCROLL:
      return "Scroll";
    case VKEY_SELECT:
      return "Select";
    case VKEY_UP:
      return "Up";
    // Standard says that DEL becomes U+007F.
    case VKEY_DELETE:
      return "U+007F";
    default:
      return String::format("U+%04X", toupper(keyCode));
  }
}

MakePlatformKeyboardEvent::MakePlatformKeyboardEvent(const WebKeyboardEvent& e)
  {
  m_type = ToPlatformKeyboardEventType(e.type);
  if (m_type == Char || m_type == KeyDown) {
#if defined(OS_MACOSX)
    m_text = &e.text[0];
    m_unmodifiedText = &e.unmodified_text[0];
    m_keyIdentifier = &e.key_identifier[0];

    // Always use 13 for Enter/Return -- we don't want to use AppKit's
    // different character for Enter.
    if (m_windowsVirtualKeyCode == '\r') {
        m_text = "\r";
        m_unmodifiedText = "\r";
    }

    // The adjustments below are only needed in backward compatibility mode,
    // but we cannot tell what mode we are in from here.

    // Turn 0x7F into 8, because backspace needs to always be 8.
    if (m_text == "\x7F")
        m_text = "\x8";
    if (m_unmodifiedText == "\x7F")
        m_unmodifiedText = "\x8";
    // Always use 9 for tab -- we don't want to use AppKit's different character for shift-tab.
    if (m_windowsVirtualKeyCode == 9) {
        m_text = "\x9";
        m_unmodifiedText = "\x9";
    }
#elif defined(OS_WIN) || defined(OS_LINUX)
    m_text = m_unmodifiedText = ToSingleCharacterString(e.key_code);
#endif
  }
#if defined(OS_WIN) || defined(OS_LINUX)
  if (m_type != Char)
    m_keyIdentifier = GetKeyIdentifierForWindowsKeyCode(e.key_code);
#endif
  if (m_type == Char || m_type == KeyDown || m_type == KeyUp ||
      m_type == RawKeyDown) {
    m_windowsVirtualKeyCode = e.key_code;
  } else {
    m_windowsVirtualKeyCode = 0;
  }
  m_autoRepeat = (e.modifiers & WebInputEvent::IS_AUTO_REPEAT) != 0;
  m_isKeypad = (e.modifiers & WebInputEvent::IS_KEYPAD) != 0;
  m_shiftKey = (e.modifiers & WebInputEvent::SHIFT_KEY) != 0;
  m_ctrlKey = (e.modifiers & WebInputEvent::CTRL_KEY) != 0;
  m_altKey = (e.modifiers & WebInputEvent::ALT_KEY) != 0;
  m_metaKey = (e.modifiers & WebInputEvent::META_KEY) != 0;
#if defined(OS_WIN)
  m_isSystemKey = e.system_key;
// TODO(port): set this field properly for linux and mac.
#elif defined(OS_LINUX)
  m_isSystemKey = m_altKey;
#else
  m_isSystemKey = false;
#endif
}

void MakePlatformKeyboardEvent::SetKeyType(Type type) {
  // According to the behavior of Webkit in Windows platform,
  // we need to convert KeyDown to RawKeydown and Char events
  // See WebKit/WebKit/Win/WebView.cpp
  ASSERT(m_type == KeyDown);
  ASSERT(type == RawKeyDown || type == Char);
  m_type = type;

  if (type == RawKeyDown) {
    m_text = String();
    m_unmodifiedText = String();
  } else {
    m_keyIdentifier = String();
    m_windowsVirtualKeyCode = 0;
  }
}

// Please refer to bug http://b/issue?id=961192, which talks about Webkit
// keyboard event handling changes. It also mentions the list of keys
// which don't have associated character events.
bool MakePlatformKeyboardEvent::IsCharacterKey() const {
  switch (windowsVirtualKeyCode()) {
    case VKEY_BACK:
    case VKEY_ESCAPE:
      return false;

    default:
      break;
  }
  return true;
}
<commit_msg>Undo part of issue 12981.<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "config.h"

#include "base/compiler_specific.h"

#include "KeyboardCodes.h"
#include "StringImpl.h"  // This is so that the KJS build works

MSVC_PUSH_WARNING_LEVEL(0);
#include "PlatformKeyboardEvent.h"
#include "PlatformMouseEvent.h"
#include "PlatformWheelEvent.h"
#include "Widget.h"
MSVC_POP_WARNING();

#undef LOG
#include "base/gfx/point.h"
#include "base/logging.h"
#include "webkit/glue/event_conversion.h"
#include "webkit/glue/webinputevent.h"
#include "webkit/glue/webkit_glue.h"

using namespace WebCore;

// MakePlatformMouseEvent -----------------------------------------------------

int MakePlatformMouseEvent::last_click_count_ = 0;
uint32 MakePlatformMouseEvent::last_click_time_ = 0;

MakePlatformMouseEvent::MakePlatformMouseEvent(Widget* widget,
                                               const WebMouseEvent& e) {
  // TODO(mpcomplete): widget is always toplevel, unless it's a popup.  We
  // may be able to get rid of this once we abstract popups into a WebKit API.
  m_position = widget->convertFromContainingWindow(IntPoint(e.x, e.y));
  m_globalPosition = IntPoint(e.global_x, e.global_y);
  m_button = static_cast<MouseButton>(e.button);
  m_shiftKey = (e.modifiers & WebInputEvent::SHIFT_KEY) != 0;
  m_ctrlKey = (e.modifiers & WebInputEvent::CTRL_KEY) != 0;
  m_altKey = (e.modifiers & WebInputEvent::ALT_KEY) != 0;
  m_metaKey = (e.modifiers & WebInputEvent::META_KEY) != 0;
  m_modifierFlags = e.modifiers;
  m_timestamp = e.timestamp_sec;

  // This differs slightly from the WebKit code in WebKit/win/WebView.cpp where
  // their original code looks buggy.
  static IntPoint last_click_position;
  static MouseButton last_click_button = LeftButton;

  const uint32 current_time = static_cast<uint32>(m_timestamp * 1000);
#if defined(OS_WIN)
  const bool cancel_previous_click =
      (abs(last_click_position.x() - m_position.x()) >
       (GetSystemMetrics(SM_CXDOUBLECLK) / 2)) ||
      (abs(last_click_position.y() - m_position.y()) >
       (GetSystemMetrics(SM_CYDOUBLECLK) / 2)) ||
      ((current_time - last_click_time_) > GetDoubleClickTime());
#elif defined(OS_MACOSX) || defined(OS_LINUX)
  const bool cancel_previous_click = false;
#endif

  switch (e.type) {
    case WebInputEvent::MOUSE_MOVE:
    case WebInputEvent::MOUSE_LEAVE:  // synthesize a move event
      if (cancel_previous_click) {
        last_click_count_ = 0;
        last_click_position = IntPoint();
        last_click_time_ = 0;
      }
      m_clickCount = last_click_count_;
      m_eventType = MouseEventMoved;
      break;

  // TODO(port): make these platform agnostic when we restructure this code.
#if defined(OS_LINUX) || defined(OS_MACOSX)
    case WebInputEvent::MOUSE_DOUBLE_CLICK:
      ++m_clickCount;
      // fall through
    case WebInputEvent::MOUSE_DOWN:
      ++m_clickCount;
      last_click_time_ = current_time;
      last_click_button = m_button;
      m_eventType = MouseEventPressed;
      break;
#else
    case WebInputEvent::MOUSE_DOWN:
    case WebInputEvent::MOUSE_DOUBLE_CLICK:
      if (!cancel_previous_click && (m_button == last_click_button)) {
        ++last_click_count_;
      } else {
        last_click_count_ = 1;
        last_click_position = m_position;
      }
      last_click_time_ = current_time;
      last_click_button = m_button;
      m_clickCount = last_click_count_;
      m_eventType = MouseEventPressed;
      break;
#endif

    case WebInputEvent::MOUSE_UP:
      m_clickCount = last_click_count_;
      m_eventType = MouseEventReleased;
      break;

    default:
      NOTREACHED() << "unexpected mouse event type";
  }

  if (webkit_glue::IsLayoutTestMode()) {
    m_clickCount = e.layout_test_click_count;
  }
}

// MakePlatformWheelEvent -----------------------------------------------------

MakePlatformWheelEvent::MakePlatformWheelEvent(Widget* widget,
                                               const WebMouseWheelEvent& e) {
  m_position = widget->convertFromContainingWindow(IntPoint(e.x, e.y));
  m_globalPosition = IntPoint(e.global_x, e.global_y);
  m_deltaX = static_cast<float>(e.delta_x);
  m_deltaY = static_cast<float>(e.delta_y);
  m_isAccepted = false;
  m_granularity = ScrollByLineWheelEvent;
  m_shiftKey = (e.modifiers & WebInputEvent::SHIFT_KEY) != 0;
  m_ctrlKey = (e.modifiers & WebInputEvent::CTRL_KEY) != 0;
  m_altKey = (e.modifiers & WebInputEvent::ALT_KEY) != 0;
  m_metaKey = (e.modifiers & WebInputEvent::META_KEY) != 0;
}

// MakePlatformKeyboardEvent --------------------------------------------------

static inline const PlatformKeyboardEvent::Type ToPlatformKeyboardEventType(
    WebInputEvent::Type type) {
  switch (type) {
    case WebInputEvent::KEY_UP:
      return PlatformKeyboardEvent::KeyUp;
    case WebInputEvent::KEY_DOWN:
      return PlatformKeyboardEvent::KeyDown;
    case WebInputEvent::CHAR:
      return PlatformKeyboardEvent::Char;
    default:
      ASSERT_NOT_REACHED();
  }
  return PlatformKeyboardEvent::KeyDown;
}

static inline String ToSingleCharacterString(UChar c) {
  return String(&c, 1);
}

static String GetKeyIdentifierForWindowsKeyCode(unsigned short keyCode) {
  switch (keyCode) {
    case VKEY_MENU:
      return "Alt";
    case VKEY_CONTROL:
      return "Control";
    case VKEY_SHIFT:
      return "Shift";
    case VKEY_CAPITAL:
      return "CapsLock";
    case VKEY_LWIN:
    case VKEY_RWIN:
      return "Win";
    case VKEY_CLEAR:
      return "Clear";
    case VKEY_DOWN:
      return "Down";
    // "End"
    case VKEY_END:
      return "End";
    // "Enter"
    case VKEY_RETURN:
      return "Enter";
    case VKEY_EXECUTE:
      return "Execute";
    case VKEY_F1:
      return "F1";
    case VKEY_F2:
      return "F2";
    case VKEY_F3:
      return "F3";
    case VKEY_F4:
      return "F4";
    case VKEY_F5:
      return "F5";
    case VKEY_F6:
      return "F6";
    case VKEY_F7:
      return "F7";
    case VKEY_F8:
      return "F8";
    case VKEY_F9:
      return "F9";
    case VKEY_F10:
      return "F11";
    case VKEY_F12:
      return "F12";
    case VKEY_F13:
      return "F13";
    case VKEY_F14:
      return "F14";
    case VKEY_F15:
      return "F15";
    case VKEY_F16:
      return "F16";
    case VKEY_F17:
      return "F17";
    case VKEY_F18:
      return "F18";
    case VKEY_F19:
      return "F19";
    case VKEY_F20:
      return "F20";
    case VKEY_F21:
      return "F21";
    case VKEY_F22:
      return "F22";
    case VKEY_F23:
      return "F23";
    case VKEY_F24:
      return "F24";
    case VKEY_HELP:
      return "Help";
    case VKEY_HOME:
      return "Home";
    case VKEY_INSERT:
      return "Insert";
    case VKEY_LEFT:
      return "Left";
    case VKEY_NEXT:
      return "PageDown";
    case VKEY_PRIOR:
      return "PageUp";
    case VKEY_PAUSE:
      return "Pause";
    case VKEY_SNAPSHOT:
      return "PrintScreen";
    case VKEY_RIGHT:
      return "Right";
    case VKEY_SCROLL:
      return "Scroll";
    case VKEY_SELECT:
      return "Select";
    case VKEY_UP:
      return "Up";
    // Standard says that DEL becomes U+007F.
    case VKEY_DELETE:
      return "U+007F";
    default:
      return String::format("U+%04X", toupper(keyCode));
  }
}

MakePlatformKeyboardEvent::MakePlatformKeyboardEvent(const WebKeyboardEvent& e)
  {
  m_type = ToPlatformKeyboardEventType(e.type);
  if (m_type == Char || m_type == KeyDown) {
#if defined(OS_MACOSX)
    m_text = &e.text[0];
    m_unmodifiedText = &e.unmodified_text[0];
    m_keyIdentifier = &e.key_identifier[0];

    // Always use 13 for Enter/Return -- we don't want to use AppKit's
    // different character for Enter.
    if (m_windowsVirtualKeyCode == '\r') {
        m_text = "\r";
        m_unmodifiedText = "\r";
    }

    // The adjustments below are only needed in backward compatibility mode,
    // but we cannot tell what mode we are in from here.

    // Turn 0x7F into 8, because backspace needs to always be 8.
    if (m_text == "\x7F")
        m_text = "\x8";
    if (m_unmodifiedText == "\x7F")
        m_unmodifiedText = "\x8";
    // Always use 9 for tab -- we don't want to use AppKit's different character for shift-tab.
    if (m_windowsVirtualKeyCode == 9) {
        m_text = "\x9";
        m_unmodifiedText = "\x9";
    }
#elif defined(OS_WIN)
    m_text = m_unmodifiedText = ToSingleCharacterString(e.key_code);
#elif defined(OS_LINUX)
    m_text = m_unmodifiedText = ToSingleCharacterString(e.text);
#endif
  }
#if defined(OS_WIN) || defined(OS_LINUX)
  if (m_type != Char)
    m_keyIdentifier = GetKeyIdentifierForWindowsKeyCode(e.key_code);
#endif
  if (m_type == Char || m_type == KeyDown || m_type == KeyUp ||
      m_type == RawKeyDown) {
    m_windowsVirtualKeyCode = e.key_code;
  } else {
    m_windowsVirtualKeyCode = 0;
  }
  m_autoRepeat = (e.modifiers & WebInputEvent::IS_AUTO_REPEAT) != 0;
  m_isKeypad = (e.modifiers & WebInputEvent::IS_KEYPAD) != 0;
  m_shiftKey = (e.modifiers & WebInputEvent::SHIFT_KEY) != 0;
  m_ctrlKey = (e.modifiers & WebInputEvent::CTRL_KEY) != 0;
  m_altKey = (e.modifiers & WebInputEvent::ALT_KEY) != 0;
  m_metaKey = (e.modifiers & WebInputEvent::META_KEY) != 0;
#if defined(OS_WIN)
  m_isSystemKey = e.system_key;
// TODO(port): set this field properly for linux and mac.
#elif defined(OS_LINUX)
  m_isSystemKey = m_altKey;
#else
  m_isSystemKey = false;
#endif
}

void MakePlatformKeyboardEvent::SetKeyType(Type type) {
  // According to the behavior of Webkit in Windows platform,
  // we need to convert KeyDown to RawKeydown and Char events
  // See WebKit/WebKit/Win/WebView.cpp
  ASSERT(m_type == KeyDown);
  ASSERT(type == RawKeyDown || type == Char);
  m_type = type;

  if (type == RawKeyDown) {
    m_text = String();
    m_unmodifiedText = String();
  } else {
    m_keyIdentifier = String();
    m_windowsVirtualKeyCode = 0;
  }
}

// Please refer to bug http://b/issue?id=961192, which talks about Webkit
// keyboard event handling changes. It also mentions the list of keys
// which don't have associated character events.
bool MakePlatformKeyboardEvent::IsCharacterKey() const {
  switch (windowsVirtualKeyCode()) {
    case VKEY_BACK:
    case VKEY_ESCAPE:
      return false;

    default:
      break;
  }
  return true;
}
<|endoftext|>


<commit_before>/**
 * The MIT License (MIT)
 *
 * Copyright © 2018-2019 Ruben Van Boxem
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 **/

#include "css/parser.h++"

#include "css/grammar.h++"

#include <core/debug.h++>

#include <boost/spirit/home/x3/core/parse.hpp>

#include <unordered_map>

namespace skui::css
{
  declaration_block parser::parse(const skui::core::string& input)
  {
    using boost::spirit::x3::phrase_parse;
    using boost::spirit::x3::space;

    declaration_block result;
    bool success = phrase_parse(input.begin(), input.end(),
                                grammar::declaration_block,//grammar::rule_set,
                                space,
                                result);

    core::debug_print("parse success: ", success, '\n');

    return result;
  }
}
<commit_msg>Comment out test that fails to compile on VS.<commit_after>/**
 * The MIT License (MIT)
 *
 * Copyright © 2018-2019 Ruben Van Boxem
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 **/

#include "css/parser.h++"

#include "css/grammar.h++"

#include <core/debug.h++>

#include <boost/spirit/home/x3/core/parse.hpp>

#include <unordered_map>
/*
namespace skui::css
{
  declaration_block parser::parse(const skui::core::string& input)
  {
    using boost::spirit::x3::phrase_parse;
    using boost::spirit::x3::space;

    declaration_block result;
    bool success = phrase_parse(input.begin(), input.end(),
                                grammar::declaration_block,//grammar::rule_set,
                                space,
                                result);

    core::debug_print("parse success: ", success, '\n');

    return result;
  }
}
*/
<|endoftext|>


<commit_before>/*-------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2019 The Khronos Group Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief SPIR-V Assembly Tests for indexing with access chain operations.
 *//*--------------------------------------------------------------------*/

#include "vktSpvAsmFromHlslTests.hpp"
#include "vktTestCaseUtil.hpp"
#include "vkPrograms.hpp"
#include "vkObjUtil.hpp"
#include "vkRefUtil.hpp"
#include "vkTypeUtil.hpp"
#include "vkQueryUtil.hpp"
#include "vkBuilderUtil.hpp"
#include "vkBarrierUtil.hpp"
#include "vkCmdUtil.hpp"

namespace vkt
{
namespace SpirVAssembly
{

namespace
{

using namespace vk;

enum TestType
{
	TT_CBUFFER_PACKING		= 0,
};

struct TestConfig
{
	TestType	type;
};

struct Programs
{
	void init (vk::SourceCollections& dst, TestConfig config) const
	{
		if (config.type == TT_CBUFFER_PACKING)
		{
			// HLSL shaders has a packing corner case that GLSL shaders cannot exhibit.
			// Below shader, foo has an ArrayStride of 16, which leaves bar effectively
			// 'within' the end of the foo array. This is entirely valid for HLSL and
			// with the VK_EXT_scalar_block_layout extension.
			std::string source(
				"cbuffer cbIn\n"
				"{\n"
				"  int foo[2] : packoffset(c0);\n"
				"  int bar    : packoffset(c1.y);\n"
				"};\n"
				"RWStructuredBuffer<int> result : register(u1);\n"
				"[numthreads(1, 1, 1)]\n"
				"void main(uint3 dispatchThreadID : SV_DispatchThreadID)\n"
				"{\n"
				"  result[0] = bar;\n"
				"}\n");

			dst.hlslSources.add("comp") << glu::ComputeSource(source)
				<< vk::ShaderBuildOptions(dst.usedVulkanVersion, vk::SPIRV_VERSION_1_0, vk::ShaderBuildOptions::FLAG_ALLOW_SCALAR_OFFSETS);
		}
	}
};

class HlslTest : public TestInstance
{
public:
						HlslTest	(Context& context, TestConfig config);
	virtual				~HlslTest	(void) = default;

	tcu::TestStatus		iterate (void);
};

HlslTest::HlslTest(Context& context, TestConfig config)
	: TestInstance(context)
{
	DE_UNREF(config);
}

tcu::TestStatus HlslTest::iterate(void)
{
	const DeviceInterface&	vk					= m_context.getDeviceInterface();
	const VkDevice			device				= m_context.getDevice();
	const VkQueue			queue				= m_context.getUniversalQueue();
	const deUint32			queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
	Allocator&				allocator			= m_context.getDefaultAllocator();
	const int				testValue			= 5;

	// Create an input buffer
	const VkBufferUsageFlags	inBufferUsageFlags		= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
	const VkDeviceSize			inBufferSizeBytes		= 32; // 2 element array with 16B stride
	VkBufferCreateInfo			inBufferCreateInfo		= makeBufferCreateInfo(inBufferSizeBytes, inBufferUsageFlags);
	vk::Move<vk::VkBuffer>		inBuffer				= createBuffer(vk, device, &inBufferCreateInfo);
	de::MovePtr<vk::Allocation>	inAllocation			= allocator.allocate(getBufferMemoryRequirements(vk, device, *inBuffer), MemoryRequirement::HostVisible);
	VK_CHECK(vk.bindBufferMemory(device, *inBuffer, inAllocation->getMemory(), inAllocation->getOffset()));

	// Fill the input structure with data - first attribute is array that has 16B stride,
	// this means that second attribute has to start at offset 20B (4B + 16B)
	{
		int* bufferPtr = static_cast<int*>(inAllocation->getHostPtr());
		memset(bufferPtr, 0, inBufferSizeBytes);
		bufferPtr[5] = testValue;
		flushAlloc(vk, device, *inAllocation);
	}

	// Create an output buffer
	const VkBufferUsageFlags	outBufferUsageFlags	= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
	const VkDeviceSize			outBufferSizeBytes	= sizeof(int);
	VkBufferCreateInfo			outBufferCreateInfo	= makeBufferCreateInfo(outBufferSizeBytes, outBufferUsageFlags);
	vk::Move<vk::VkBuffer>		outBuffer			= createBuffer(vk, device, &outBufferCreateInfo);
	de::MovePtr<vk::Allocation>	outAllocation		= allocator.allocate(getBufferMemoryRequirements(vk, device, *outBuffer), MemoryRequirement::HostVisible);
	VK_CHECK(vk.bindBufferMemory(device, *outBuffer, outAllocation->getMemory(), outAllocation->getOffset()));

	// Create descriptor set
	const VkDescriptorType uniBufDesc	= VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
	const VkDescriptorType storBufDesc	= VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
	const Unique<VkDescriptorSetLayout> descriptorSetLayout(
		DescriptorSetLayoutBuilder()
		.addSingleBinding(uniBufDesc, VK_SHADER_STAGE_COMPUTE_BIT)
		.addSingleBinding(storBufDesc, VK_SHADER_STAGE_COMPUTE_BIT)
		.build(vk, device));

	const Unique<VkDescriptorPool> descriptorPool(
		DescriptorPoolBuilder()
		.addType(uniBufDesc)
		.addType(storBufDesc)
		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));

	const Unique<VkDescriptorSet> descriptorSet(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));

	const VkDescriptorBufferInfo inputBufferDescriptorInfo = makeDescriptorBufferInfo(*inBuffer, 0ull, inBufferSizeBytes);
	const VkDescriptorBufferInfo outputBufferDescriptorInfo = makeDescriptorBufferInfo(*outBuffer, 0ull, outBufferSizeBytes);
	DescriptorSetUpdateBuilder()
		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), uniBufDesc, &inputBufferDescriptorInfo)
		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), storBufDesc, &outputBufferDescriptorInfo)
		.update(vk, device);

	// Perform the computation
	const Unique<VkShaderModule> shaderModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0u));
	const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));

	const VkPipelineShaderStageCreateInfo pipelineShaderStageParams =
	{
		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
		DE_NULL,
		static_cast<VkPipelineShaderStageCreateFlags>(0u),
		VK_SHADER_STAGE_COMPUTE_BIT,
		*shaderModule,
		"main",
		DE_NULL,
	};
	const VkComputePipelineCreateInfo pipelineCreateInfo =
	{
		VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
		DE_NULL,
		static_cast<VkPipelineCreateFlags>(0u),
		pipelineShaderStageParams,
		*pipelineLayout,
		DE_NULL,
		0,
	};
	Unique<VkPipeline> pipeline(createComputePipeline(vk, device, DE_NULL, &pipelineCreateInfo));
	const VkBufferMemoryBarrier hostWriteBarrier = makeBufferMemoryBarrier(VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, *inBuffer, 0ull, inBufferSizeBytes);
	const VkBufferMemoryBarrier shaderWriteBarrier = makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *outBuffer, 0ull, outBufferSizeBytes);

	const Unique<VkCommandPool> cmdPool(makeCommandPool(vk, device, queueFamilyIndex));
	const Unique<VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));

	// Start recording commands
	beginCommandBuffer(vk, *cmdBuffer);

	vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
	vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);

	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &hostWriteBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
	vk.cmdDispatch(*cmdBuffer, 1, 1, 1);
	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &shaderWriteBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);

	endCommandBuffer(vk, *cmdBuffer);

	// Wait for completion
	submitCommandsAndWait(vk, device, queue, *cmdBuffer);

	// Validate the results
	invalidateAlloc(vk, device, *outAllocation);
	const int* bufferPtr = static_cast<int*>(outAllocation->getHostPtr());
	if (*bufferPtr != testValue)
		return tcu::TestStatus::fail("Fail");
	return tcu::TestStatus::pass("Pass");
}

} // anonymous

tcu::TestCaseGroup* createHlslComputeGroup (tcu::TestContext& testCtx)
{
	typedef InstanceFactory1<HlslTest, TestConfig, Programs> HlslTestInstance;
	de::MovePtr<tcu::TestCaseGroup> hlslCasesGroup(new tcu::TestCaseGroup(testCtx, "hlsl_cases", ""));

	TestConfig testConfig = { TT_CBUFFER_PACKING };
	hlslCasesGroup->addChild(new HlslTestInstance(testCtx, tcu::NODETYPE_SELF_VALIDATE, "cbuffer_packing", "", testConfig));

	return hlslCasesGroup.release();
}

} // SpirVAssembly
} // vkt
<commit_msg>Fix cbuffer packing test<commit_after>/*-------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2019 The Khronos Group Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief SPIR-V Assembly Tests for indexing with access chain operations.
 *//*--------------------------------------------------------------------*/

#include "vktSpvAsmFromHlslTests.hpp"
#include "vktTestCaseUtil.hpp"
#include "vkPrograms.hpp"
#include "vkObjUtil.hpp"
#include "vkRefUtil.hpp"
#include "vkTypeUtil.hpp"
#include "vkQueryUtil.hpp"
#include "vkBuilderUtil.hpp"
#include "vkBarrierUtil.hpp"
#include "vkCmdUtil.hpp"

namespace vkt
{
namespace SpirVAssembly
{

namespace
{

using namespace vk;

enum TestType
{
	TT_CBUFFER_PACKING		= 0,
};

struct TestConfig
{
	TestType	type;
};

struct Programs
{
	void init (vk::SourceCollections& dst, TestConfig config) const
	{
		if (config.type == TT_CBUFFER_PACKING)
		{
			// HLSL shaders has a packing corner case that GLSL shaders cannot exhibit.
			// Below shader, foo has an ArrayStride of 16, which leaves bar effectively
			// 'within' the end of the foo array. This is entirely valid for HLSL and
			// with the VK_EXT_scalar_block_layout extension.
			std::string source(
				"cbuffer cbIn\n"
				"{\n"
				"  int foo[2] : packoffset(c0);\n"
				"  int bar    : packoffset(c1.y);\n"
				"};\n"
				"RWStructuredBuffer<int> result : register(u1);\n"
				"[numthreads(1, 1, 1)]\n"
				"void main(uint3 dispatchThreadID : SV_DispatchThreadID)\n"
				"{\n"
				"  result[0] = bar;\n"
				"}\n");

			dst.hlslSources.add("comp") << glu::ComputeSource(source)
				<< vk::ShaderBuildOptions(dst.usedVulkanVersion, vk::SPIRV_VERSION_1_0, vk::ShaderBuildOptions::FLAG_ALLOW_SCALAR_OFFSETS);
		}
	}
};

class HlslTest : public TestInstance
{
public:
						HlslTest	(Context& context, TestConfig config);
	virtual				~HlslTest	(void) = default;

	tcu::TestStatus		iterate (void);
};

HlslTest::HlslTest(Context& context, TestConfig config)
	: TestInstance(context)
{
	DE_UNREF(config);
}

tcu::TestStatus HlslTest::iterate(void)
{
	const DeviceInterface&	vk					= m_context.getDeviceInterface();
	const VkDevice			device				= m_context.getDevice();
	const VkQueue			queue				= m_context.getUniversalQueue();
	const deUint32			queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
	Allocator&				allocator			= m_context.getDefaultAllocator();
	const int				testValue			= 5;

	// Create an input buffer
	const VkBufferUsageFlags	inBufferUsageFlags		= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
	const VkDeviceSize			inBufferSizeBytes		= 32; // 2 element array with 16B stride
	VkBufferCreateInfo			inBufferCreateInfo		= makeBufferCreateInfo(inBufferSizeBytes, inBufferUsageFlags);
	vk::Move<vk::VkBuffer>		inBuffer				= createBuffer(vk, device, &inBufferCreateInfo);
	de::MovePtr<vk::Allocation>	inAllocation			= allocator.allocate(getBufferMemoryRequirements(vk, device, *inBuffer), MemoryRequirement::HostVisible);
	VK_CHECK(vk.bindBufferMemory(device, *inBuffer, inAllocation->getMemory(), inAllocation->getOffset()));

	// Fill the input structure with data - first attribute is array that has 16B stride,
	// this means that second attribute has to start at offset 20B (4B + 16B)
	{
		int* bufferPtr = static_cast<int*>(inAllocation->getHostPtr());
		memset(bufferPtr, 0, inBufferSizeBytes);
		bufferPtr[5] = testValue;
		flushAlloc(vk, device, *inAllocation);
	}

	// Create an output buffer
	const VkBufferUsageFlags	outBufferUsageFlags	= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
	const VkDeviceSize			outBufferSizeBytes	= sizeof(int);
	VkBufferCreateInfo			outBufferCreateInfo	= makeBufferCreateInfo(outBufferSizeBytes, outBufferUsageFlags);
	vk::Move<vk::VkBuffer>		outBuffer			= createBuffer(vk, device, &outBufferCreateInfo);
	de::MovePtr<vk::Allocation>	outAllocation		= allocator.allocate(getBufferMemoryRequirements(vk, device, *outBuffer), MemoryRequirement::HostVisible);
	VK_CHECK(vk.bindBufferMemory(device, *outBuffer, outAllocation->getMemory(), outAllocation->getOffset()));

	// Create descriptor set
	const VkDescriptorType uniBufDesc	= VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
	const VkDescriptorType storBufDesc	= VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
	const Unique<VkDescriptorSetLayout> descriptorSetLayout(
		DescriptorSetLayoutBuilder()
		.addSingleBinding(uniBufDesc, VK_SHADER_STAGE_COMPUTE_BIT)
		.addSingleBinding(storBufDesc, VK_SHADER_STAGE_COMPUTE_BIT)
		.build(vk, device));

	const Unique<VkDescriptorPool> descriptorPool(
		DescriptorPoolBuilder()
		.addType(uniBufDesc)
		.addType(storBufDesc)
		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));

	const Unique<VkDescriptorSet> descriptorSet(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));

	const VkDescriptorBufferInfo inputBufferDescriptorInfo = makeDescriptorBufferInfo(*inBuffer, 0ull, inBufferSizeBytes);
	const VkDescriptorBufferInfo outputBufferDescriptorInfo = makeDescriptorBufferInfo(*outBuffer, 0ull, outBufferSizeBytes);
	DescriptorSetUpdateBuilder()
		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), uniBufDesc, &inputBufferDescriptorInfo)
		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), storBufDesc, &outputBufferDescriptorInfo)
		.update(vk, device);

	// Perform the computation
	const Unique<VkShaderModule> shaderModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0u));
	const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));

	const VkPipelineShaderStageCreateInfo pipelineShaderStageParams =
	{
		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
		DE_NULL,
		static_cast<VkPipelineShaderStageCreateFlags>(0u),
		VK_SHADER_STAGE_COMPUTE_BIT,
		*shaderModule,
		"main",
		DE_NULL,
	};
	const VkComputePipelineCreateInfo pipelineCreateInfo =
	{
		VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
		DE_NULL,
		static_cast<VkPipelineCreateFlags>(0u),
		pipelineShaderStageParams,
		*pipelineLayout,
		DE_NULL,
		0,
	};
	Unique<VkPipeline> pipeline(createComputePipeline(vk, device, DE_NULL, &pipelineCreateInfo));
	const VkBufferMemoryBarrier hostWriteBarrier = makeBufferMemoryBarrier(VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, *inBuffer, 0ull, inBufferSizeBytes);
	const VkBufferMemoryBarrier shaderWriteBarrier = makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *outBuffer, 0ull, outBufferSizeBytes);

	const Unique<VkCommandPool> cmdPool(makeCommandPool(vk, device, queueFamilyIndex));
	const Unique<VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));

	// Start recording commands
	beginCommandBuffer(vk, *cmdBuffer);

	vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
	vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);

	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &hostWriteBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
	vk.cmdDispatch(*cmdBuffer, 1, 1, 1);
	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &shaderWriteBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);

	endCommandBuffer(vk, *cmdBuffer);

	// Wait for completion
	submitCommandsAndWait(vk, device, queue, *cmdBuffer);

	// Validate the results
	invalidateAlloc(vk, device, *outAllocation);
	const int* bufferPtr = static_cast<int*>(outAllocation->getHostPtr());
	if (*bufferPtr != testValue)
		return tcu::TestStatus::fail("Fail");
	return tcu::TestStatus::pass("Pass");
}

void checkSupport(Context& context)
{
	context.requireDeviceFunctionality("VK_EXT_scalar_block_layout");
}

} // anonymous

tcu::TestCaseGroup* createHlslComputeGroup (tcu::TestContext& testCtx)
{
	typedef InstanceFactory1WithSupport<HlslTest, TestConfig, FunctionSupport0, Programs> HlslTestInstance;
	de::MovePtr<tcu::TestCaseGroup> hlslCasesGroup(new tcu::TestCaseGroup(testCtx, "hlsl_cases", ""));

	TestConfig testConfig = { TT_CBUFFER_PACKING };
	hlslCasesGroup->addChild(new HlslTestInstance(testCtx, tcu::NODETYPE_SELF_VALIDATE, "cbuffer_packing", "", testConfig, checkSupport));

	return hlslCasesGroup.release();
}

} // SpirVAssembly
} // vkt
<|endoftext|>