<commit_before>//===-- AMDGPUAsmPrinter.cpp - AMDGPU Assebly printer  --------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
/// \file
///
/// The AMDGPUAsmPrinter is used to print both assembly string and also binary
/// code.  When passed an MCAsmStreamer it prints assembly and when passed
/// an MCObjectStreamer it outputs binary code.
//
//===----------------------------------------------------------------------===//
//

#include "AMDGPUAsmPrinter.h"
#include "AMDGPU.h"
#include "R600Defines.h"
#include "R600MachineFunctionInfo.h"
#include "R600RegisterInfo.h"
#include "SIDefines.h"
#include "SIMachineFunctionInfo.h"
#include "SIRegisterInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Target/TargetLoweringObjectFile.h"

using namespace llvm;

static AsmPrinter *createAMDGPUAsmPrinterPass(TargetMachine &tm,
                                              MCStreamer &Streamer) {
  return new AMDGPUAsmPrinter(tm, Streamer);
}

extern "C" void LLVMInitializeR600AsmPrinter() {
  TargetRegistry::RegisterAsmPrinter(TheAMDGPUTarget, createAMDGPUAsmPrinterPass);
}

AMDGPUAsmPrinter::AMDGPUAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
    : AsmPrinter(TM, Streamer) {
  DisasmEnabled = TM.getSubtarget<AMDGPUSubtarget>().dumpCode() &&
                  ! Streamer.hasRawTextSupport();
}

/// We need to override this function so we can avoid
/// the call to EmitFunctionHeader(), which the MCPureStreamer can't handle.
bool AMDGPUAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
  SetupMachineFunction(MF);

  if (OutStreamer.hasRawTextSupport()) {
    OutStreamer.EmitRawText("@" + MF.getName() + ":");
  }

  MCContext &Context = getObjFileLowering().getContext();
  const MCSectionELF *ConfigSection = Context.getELFSection(".AMDGPU.config",
                                              ELF::SHT_PROGBITS, 0,
                                              SectionKind::getReadOnly());
  OutStreamer.SwitchSection(ConfigSection);

  const AMDGPUSubtarget &STM = TM.getSubtarget<AMDGPUSubtarget>();
  SIProgramInfo KernelInfo;
  if (STM.getGeneration() > AMDGPUSubtarget::NORTHERN_ISLANDS) {
    findNumUsedRegistersSI(MF, KernelInfo.NumSGPR, KernelInfo.NumVGPR);
    EmitProgramInfoSI(MF, KernelInfo);
  } else {
    EmitProgramInfoR600(MF);
  }

  DisasmLines.clear();
  HexLines.clear();
  DisasmLineMaxLen = 0;

  OutStreamer.SwitchSection(getObjFileLowering().getTextSection());
  EmitFunctionBody();

  if (isVerbose() && OutStreamer.hasRawTextSupport()) {
    const MCSectionELF *CommentSection
      = Context.getELFSection(".AMDGPU.csdata",
                              ELF::SHT_PROGBITS, 0,
                              SectionKind::getReadOnly());
    OutStreamer.SwitchSection(CommentSection);

    if (STM.getGeneration() > AMDGPUSubtarget::NORTHERN_ISLANDS) {
      OutStreamer.emitRawComment(" Kernel info:", false);
      OutStreamer.emitRawComment(" NumSgprs: " + Twine(KernelInfo.NumSGPR),
                                 false);
      OutStreamer.emitRawComment(" NumVgprs: " + Twine(KernelInfo.NumVGPR),
                                 false);
    } else {
      R600MachineFunctionInfo *MFI = MF.getInfo<R600MachineFunctionInfo>();
      OutStreamer.EmitRawText(
        Twine("SQ_PGM_RESOURCES:STACK_SIZE = " + Twine(MFI->StackSize)));
    }
  }

  if (STM.dumpCode()) {
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
    MF.dump();
#endif

    if (DisasmEnabled) {
      OutStreamer.SwitchSection(Context.getELFSection(".AMDGPU.disasm",
                                                  ELF::SHT_NOTE, 0,
                                                  SectionKind::getReadOnly()));

      for (size_t i = 0; i < DisasmLines.size(); ++i) {
        std::string Comment(DisasmLineMaxLen - DisasmLines[i].size(), ' ');
        Comment += " ; " + HexLines[i] + "\n";

        OutStreamer.EmitBytes(StringRef(DisasmLines[i]));
        OutStreamer.EmitBytes(StringRef(Comment));
      }
    }
  }

  return false;
}

void AMDGPUAsmPrinter::EmitProgramInfoR600(MachineFunction &MF) {
  unsigned MaxGPR = 0;
  bool killPixel = false;
  const R600RegisterInfo * RI =
                static_cast<const R600RegisterInfo*>(TM.getRegisterInfo());
  R600MachineFunctionInfo *MFI = MF.getInfo<R600MachineFunctionInfo>();
  const AMDGPUSubtarget &STM = TM.getSubtarget<AMDGPUSubtarget>();

  for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end();
                                                  BB != BB_E; ++BB) {
    MachineBasicBlock &MBB = *BB;
    for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
                                                    I != E; ++I) {
      MachineInstr &MI = *I;
      if (MI.getOpcode() == AMDGPU::KILLGT)
        killPixel = true;
      unsigned numOperands = MI.getNumOperands();
      for (unsigned op_idx = 0; op_idx < numOperands; op_idx++) {
        MachineOperand & MO = MI.getOperand(op_idx);
        if (!MO.isReg())
          continue;
        unsigned HWReg = RI->getEncodingValue(MO.getReg()) & 0xff;

        // Register with value > 127 aren't GPR
        if (HWReg > 127)
          continue;
        MaxGPR = std::max(MaxGPR, HWReg);
      }
    }
  }

  unsigned RsrcReg;
  if (STM.getGeneration() >= AMDGPUSubtarget::EVERGREEN) {
    // Evergreen / Northern Islands
    switch (MFI->ShaderType) {
    default: // Fall through
    case ShaderType::COMPUTE:  RsrcReg = R_0288D4_SQ_PGM_RESOURCES_LS; break;
    case ShaderType::GEOMETRY: RsrcReg = R_028878_SQ_PGM_RESOURCES_GS; break;
    case ShaderType::PIXEL:    RsrcReg = R_028844_SQ_PGM_RESOURCES_PS; break;
    case ShaderType::VERTEX:   RsrcReg = R_028860_SQ_PGM_RESOURCES_VS; break;
    }
  } else {
    // R600 / R700
    switch (MFI->ShaderType) {
    default: // Fall through
    case ShaderType::GEOMETRY: // Fall through
    case ShaderType::COMPUTE:  // Fall through
    case ShaderType::VERTEX:   RsrcReg = R_028868_SQ_PGM_RESOURCES_VS; break;
    case ShaderType::PIXEL:    RsrcReg = R_028850_SQ_PGM_RESOURCES_PS; break;
    }
  }

  OutStreamer.EmitIntValue(RsrcReg, 4);
  OutStreamer.EmitIntValue(S_NUM_GPRS(MaxGPR + 1) |
                           S_STACK_SIZE(MFI->StackSize), 4);
  OutStreamer.EmitIntValue(R_02880C_DB_SHADER_CONTROL, 4);
  OutStreamer.EmitIntValue(S_02880C_KILL_ENABLE(killPixel), 4);

  if (MFI->ShaderType == ShaderType::COMPUTE) {
    OutStreamer.EmitIntValue(R_0288E8_SQ_LDS_ALLOC, 4);
    OutStreamer.EmitIntValue(RoundUpToAlignment(MFI->LDSSize, 4) >> 2, 4);
  }
}

void AMDGPUAsmPrinter::findNumUsedRegistersSI(MachineFunction &MF,
                                              unsigned &NumSGPR,
                                              unsigned &NumVGPR) const {
  unsigned MaxSGPR = 0;
  unsigned MaxVGPR = 0;
  bool VCCUsed = false;
  const SIRegisterInfo * RI =
                static_cast<const SIRegisterInfo*>(TM.getRegisterInfo());

  for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end();
                                                  BB != BB_E; ++BB) {
    MachineBasicBlock &MBB = *BB;
    for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
                                                    I != E; ++I) {
      MachineInstr &MI = *I;

      unsigned numOperands = MI.getNumOperands();
      for (unsigned op_idx = 0; op_idx < numOperands; op_idx++) {
        MachineOperand &MO = MI.getOperand(op_idx);
        unsigned width = 0;
        bool isSGPR = false;

        if (!MO.isReg()) {
          continue;
        }
        unsigned reg = MO.getReg();
        if (reg == AMDGPU::VCC) {
          VCCUsed = true;
          continue;
        }

        switch (reg) {
        default: break;
        case AMDGPU::SCC:
        case AMDGPU::EXEC:
        case AMDGPU::M0:
          continue;
        }

        if (AMDGPU::SReg_32RegClass.contains(reg)) {
          isSGPR = true;
          width = 1;
        } else if (AMDGPU::VReg_32RegClass.contains(reg)) {
          isSGPR = false;
          width = 1;
        } else if (AMDGPU::SReg_64RegClass.contains(reg)) {
          isSGPR = true;
          width = 2;
        } else if (AMDGPU::VReg_64RegClass.contains(reg)) {
          isSGPR = false;
          width = 2;
        } else if (AMDGPU::VReg_96RegClass.contains(reg)) {
          isSGPR = false;
          width = 3;
        } else if (AMDGPU::SReg_128RegClass.contains(reg)) {
          isSGPR = true;
          width = 4;
        } else if (AMDGPU::VReg_128RegClass.contains(reg)) {
          isSGPR = false;
          width = 4;
        } else if (AMDGPU::SReg_256RegClass.contains(reg)) {
          isSGPR = true;
          width = 8;
        } else if (AMDGPU::VReg_256RegClass.contains(reg)) {
          isSGPR = false;
          width = 8;
        } else if (AMDGPU::SReg_512RegClass.contains(reg)) {
          isSGPR = true;
          width = 16;
        } else if (AMDGPU::VReg_512RegClass.contains(reg)) {
          isSGPR = false;
          width = 16;
        } else {
          llvm_unreachable("Unknown register class");
        }
        unsigned hwReg = RI->getEncodingValue(reg) & 0xff;
        unsigned maxUsed = hwReg + width - 1;
        if (isSGPR) {
          MaxSGPR = maxUsed > MaxSGPR ? maxUsed : MaxSGPR;
        } else {
          MaxVGPR = maxUsed > MaxVGPR ? maxUsed : MaxVGPR;
        }
      }
    }
  }

  if (VCCUsed)
    MaxSGPR += 2;

  NumSGPR = MaxSGPR;
  NumVGPR = MaxVGPR;
}

void AMDGPUAsmPrinter::getSIProgramInfo(SIProgramInfo &Out,
                                        MachineFunction &MF) const {
  findNumUsedRegistersSI(MF, Out.NumSGPR, Out.NumVGPR);
}

void AMDGPUAsmPrinter::EmitProgramInfoSI(MachineFunction &MF,
                                         const SIProgramInfo &KernelInfo) {
  const AMDGPUSubtarget &STM = TM.getSubtarget<AMDGPUSubtarget>();

  SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
  unsigned RsrcReg;
  switch (MFI->ShaderType) {
  default: // Fall through
  case ShaderType::COMPUTE:  RsrcReg = R_00B848_COMPUTE_PGM_RSRC1; break;
  case ShaderType::GEOMETRY: RsrcReg = R_00B228_SPI_SHADER_PGM_RSRC1_GS; break;
  case ShaderType::PIXEL:    RsrcReg = R_00B028_SPI_SHADER_PGM_RSRC1_PS; break;
  case ShaderType::VERTEX:   RsrcReg = R_00B128_SPI_SHADER_PGM_RSRC1_VS; break;
  }

  OutStreamer.EmitIntValue(RsrcReg, 4);
  OutStreamer.EmitIntValue(S_00B028_VGPRS(KernelInfo.NumVGPR / 4) |
                           S_00B028_SGPRS(KernelInfo.NumSGPR / 8), 4);

  unsigned LDSAlignShift;
  if (STM.getGeneration() < AMDGPUSubtarget::SEA_ISLANDS) {
    // LDS is allocated in 64 dword blocks
    LDSAlignShift = 8;
  } else {
    // LDS is allocated in 128 dword blocks
    LDSAlignShift = 9;
  }
  unsigned LDSBlocks =
          RoundUpToAlignment(MFI->LDSSize, 1 << LDSAlignShift) >> LDSAlignShift;

  if (MFI->ShaderType == ShaderType::COMPUTE) {
    OutStreamer.EmitIntValue(R_00B84C_COMPUTE_PGM_RSRC2, 4);
    OutStreamer.EmitIntValue(S_00B84C_LDS_SIZE(LDSBlocks), 4);
  }
  if (MFI->ShaderType == ShaderType::PIXEL) {
    OutStreamer.EmitIntValue(R_00B02C_SPI_SHADER_PGM_RSRC2_PS, 4);
    OutStreamer.EmitIntValue(S_00B02C_EXTRA_LDS_SIZE(LDSBlocks), 4);
    OutStreamer.EmitIntValue(R_0286CC_SPI_PS_INPUT_ENA, 4);
    OutStreamer.EmitIntValue(MFI->PSInputAddr, 4);
  }
}
<commit_msg>Use emitRawComment to avoid a call to hasRawTextSupport.<commit_after>//===-- AMDGPUAsmPrinter.cpp - AMDGPU Assebly printer  --------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
/// \file
///
/// The AMDGPUAsmPrinter is used to print both assembly string and also binary
/// code.  When passed an MCAsmStreamer it prints assembly and when passed
/// an MCObjectStreamer it outputs binary code.
//
//===----------------------------------------------------------------------===//
//

#include "AMDGPUAsmPrinter.h"
#include "AMDGPU.h"
#include "R600Defines.h"
#include "R600MachineFunctionInfo.h"
#include "R600RegisterInfo.h"
#include "SIDefines.h"
#include "SIMachineFunctionInfo.h"
#include "SIRegisterInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Target/TargetLoweringObjectFile.h"

using namespace llvm;

static AsmPrinter *createAMDGPUAsmPrinterPass(TargetMachine &tm,
                                              MCStreamer &Streamer) {
  return new AMDGPUAsmPrinter(tm, Streamer);
}

extern "C" void LLVMInitializeR600AsmPrinter() {
  TargetRegistry::RegisterAsmPrinter(TheAMDGPUTarget, createAMDGPUAsmPrinterPass);
}

AMDGPUAsmPrinter::AMDGPUAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
    : AsmPrinter(TM, Streamer) {
  DisasmEnabled = TM.getSubtarget<AMDGPUSubtarget>().dumpCode() &&
                  ! Streamer.hasRawTextSupport();
}

/// We need to override this function so we can avoid
/// the call to EmitFunctionHeader(), which the MCPureStreamer can't handle.
bool AMDGPUAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
  SetupMachineFunction(MF);

  OutStreamer.emitRawComment(Twine('@') + MF.getName() + Twine(':'));

  MCContext &Context = getObjFileLowering().getContext();
  const MCSectionELF *ConfigSection = Context.getELFSection(".AMDGPU.config",
                                              ELF::SHT_PROGBITS, 0,
                                              SectionKind::getReadOnly());
  OutStreamer.SwitchSection(ConfigSection);

  const AMDGPUSubtarget &STM = TM.getSubtarget<AMDGPUSubtarget>();
  SIProgramInfo KernelInfo;
  if (STM.getGeneration() > AMDGPUSubtarget::NORTHERN_ISLANDS) {
    findNumUsedRegistersSI(MF, KernelInfo.NumSGPR, KernelInfo.NumVGPR);
    EmitProgramInfoSI(MF, KernelInfo);
  } else {
    EmitProgramInfoR600(MF);
  }

  DisasmLines.clear();
  HexLines.clear();
  DisasmLineMaxLen = 0;

  OutStreamer.SwitchSection(getObjFileLowering().getTextSection());
  EmitFunctionBody();

  if (isVerbose() && OutStreamer.hasRawTextSupport()) {
    const MCSectionELF *CommentSection
      = Context.getELFSection(".AMDGPU.csdata",
                              ELF::SHT_PROGBITS, 0,
                              SectionKind::getReadOnly());
    OutStreamer.SwitchSection(CommentSection);

    if (STM.getGeneration() > AMDGPUSubtarget::NORTHERN_ISLANDS) {
      OutStreamer.emitRawComment(" Kernel info:", false);
      OutStreamer.emitRawComment(" NumSgprs: " + Twine(KernelInfo.NumSGPR),
                                 false);
      OutStreamer.emitRawComment(" NumVgprs: " + Twine(KernelInfo.NumVGPR),
                                 false);
    } else {
      R600MachineFunctionInfo *MFI = MF.getInfo<R600MachineFunctionInfo>();
      OutStreamer.EmitRawText(
        Twine("SQ_PGM_RESOURCES:STACK_SIZE = " + Twine(MFI->StackSize)));
    }
  }

  if (STM.dumpCode()) {
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
    MF.dump();
#endif

    if (DisasmEnabled) {
      OutStreamer.SwitchSection(Context.getELFSection(".AMDGPU.disasm",
                                                  ELF::SHT_NOTE, 0,
                                                  SectionKind::getReadOnly()));

      for (size_t i = 0; i < DisasmLines.size(); ++i) {
        std::string Comment(DisasmLineMaxLen - DisasmLines[i].size(), ' ');
        Comment += " ; " + HexLines[i] + "\n";

        OutStreamer.EmitBytes(StringRef(DisasmLines[i]));
        OutStreamer.EmitBytes(StringRef(Comment));
      }
    }
  }

  return false;
}

void AMDGPUAsmPrinter::EmitProgramInfoR600(MachineFunction &MF) {
  unsigned MaxGPR = 0;
  bool killPixel = false;
  const R600RegisterInfo * RI =
                static_cast<const R600RegisterInfo*>(TM.getRegisterInfo());
  R600MachineFunctionInfo *MFI = MF.getInfo<R600MachineFunctionInfo>();
  const AMDGPUSubtarget &STM = TM.getSubtarget<AMDGPUSubtarget>();

  for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end();
                                                  BB != BB_E; ++BB) {
    MachineBasicBlock &MBB = *BB;
    for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
                                                    I != E; ++I) {
      MachineInstr &MI = *I;
      if (MI.getOpcode() == AMDGPU::KILLGT)
        killPixel = true;
      unsigned numOperands = MI.getNumOperands();
      for (unsigned op_idx = 0; op_idx < numOperands; op_idx++) {
        MachineOperand & MO = MI.getOperand(op_idx);
        if (!MO.isReg())
          continue;
        unsigned HWReg = RI->getEncodingValue(MO.getReg()) & 0xff;

        // Register with value > 127 aren't GPR
        if (HWReg > 127)
          continue;
        MaxGPR = std::max(MaxGPR, HWReg);
      }
    }
  }

  unsigned RsrcReg;
  if (STM.getGeneration() >= AMDGPUSubtarget::EVERGREEN) {
    // Evergreen / Northern Islands
    switch (MFI->ShaderType) {
    default: // Fall through
    case ShaderType::COMPUTE:  RsrcReg = R_0288D4_SQ_PGM_RESOURCES_LS; break;
    case ShaderType::GEOMETRY: RsrcReg = R_028878_SQ_PGM_RESOURCES_GS; break;
    case ShaderType::PIXEL:    RsrcReg = R_028844_SQ_PGM_RESOURCES_PS; break;
    case ShaderType::VERTEX:   RsrcReg = R_028860_SQ_PGM_RESOURCES_VS; break;
    }
  } else {
    // R600 / R700
    switch (MFI->ShaderType) {
    default: // Fall through
    case ShaderType::GEOMETRY: // Fall through
    case ShaderType::COMPUTE:  // Fall through
    case ShaderType::VERTEX:   RsrcReg = R_028868_SQ_PGM_RESOURCES_VS; break;
    case ShaderType::PIXEL:    RsrcReg = R_028850_SQ_PGM_RESOURCES_PS; break;
    }
  }

  OutStreamer.EmitIntValue(RsrcReg, 4);
  OutStreamer.EmitIntValue(S_NUM_GPRS(MaxGPR + 1) |
                           S_STACK_SIZE(MFI->StackSize), 4);
  OutStreamer.EmitIntValue(R_02880C_DB_SHADER_CONTROL, 4);
  OutStreamer.EmitIntValue(S_02880C_KILL_ENABLE(killPixel), 4);

  if (MFI->ShaderType == ShaderType::COMPUTE) {
    OutStreamer.EmitIntValue(R_0288E8_SQ_LDS_ALLOC, 4);
    OutStreamer.EmitIntValue(RoundUpToAlignment(MFI->LDSSize, 4) >> 2, 4);
  }
}

void AMDGPUAsmPrinter::findNumUsedRegistersSI(MachineFunction &MF,
                                              unsigned &NumSGPR,
                                              unsigned &NumVGPR) const {
  unsigned MaxSGPR = 0;
  unsigned MaxVGPR = 0;
  bool VCCUsed = false;
  const SIRegisterInfo * RI =
                static_cast<const SIRegisterInfo*>(TM.getRegisterInfo());

  for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end();
                                                  BB != BB_E; ++BB) {
    MachineBasicBlock &MBB = *BB;
    for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
                                                    I != E; ++I) {
      MachineInstr &MI = *I;

      unsigned numOperands = MI.getNumOperands();
      for (unsigned op_idx = 0; op_idx < numOperands; op_idx++) {
        MachineOperand &MO = MI.getOperand(op_idx);
        unsigned width = 0;
        bool isSGPR = false;

        if (!MO.isReg()) {
          continue;
        }
        unsigned reg = MO.getReg();
        if (reg == AMDGPU::VCC) {
          VCCUsed = true;
          continue;
        }

        switch (reg) {
        default: break;
        case AMDGPU::SCC:
        case AMDGPU::EXEC:
        case AMDGPU::M0:
          continue;
        }

        if (AMDGPU::SReg_32RegClass.contains(reg)) {
          isSGPR = true;
          width = 1;
        } else if (AMDGPU::VReg_32RegClass.contains(reg)) {
          isSGPR = false;
          width = 1;
        } else if (AMDGPU::SReg_64RegClass.contains(reg)) {
          isSGPR = true;
          width = 2;
        } else if (AMDGPU::VReg_64RegClass.contains(reg)) {
          isSGPR = false;
          width = 2;
        } else if (AMDGPU::VReg_96RegClass.contains(reg)) {
          isSGPR = false;
          width = 3;
        } else if (AMDGPU::SReg_128RegClass.contains(reg)) {
          isSGPR = true;
          width = 4;
        } else if (AMDGPU::VReg_128RegClass.contains(reg)) {
          isSGPR = false;
          width = 4;
        } else if (AMDGPU::SReg_256RegClass.contains(reg)) {
          isSGPR = true;
          width = 8;
        } else if (AMDGPU::VReg_256RegClass.contains(reg)) {
          isSGPR = false;
          width = 8;
        } else if (AMDGPU::SReg_512RegClass.contains(reg)) {
          isSGPR = true;
          width = 16;
        } else if (AMDGPU::VReg_512RegClass.contains(reg)) {
          isSGPR = false;
          width = 16;
        } else {
          llvm_unreachable("Unknown register class");
        }
        unsigned hwReg = RI->getEncodingValue(reg) & 0xff;
        unsigned maxUsed = hwReg + width - 1;
        if (isSGPR) {
          MaxSGPR = maxUsed > MaxSGPR ? maxUsed : MaxSGPR;
        } else {
          MaxVGPR = maxUsed > MaxVGPR ? maxUsed : MaxVGPR;
        }
      }
    }
  }

  if (VCCUsed)
    MaxSGPR += 2;

  NumSGPR = MaxSGPR;
  NumVGPR = MaxVGPR;
}

void AMDGPUAsmPrinter::getSIProgramInfo(SIProgramInfo &Out,
                                        MachineFunction &MF) const {
  findNumUsedRegistersSI(MF, Out.NumSGPR, Out.NumVGPR);
}

void AMDGPUAsmPrinter::EmitProgramInfoSI(MachineFunction &MF,
                                         const SIProgramInfo &KernelInfo) {
  const AMDGPUSubtarget &STM = TM.getSubtarget<AMDGPUSubtarget>();

  SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
  unsigned RsrcReg;
  switch (MFI->ShaderType) {
  default: // Fall through
  case ShaderType::COMPUTE:  RsrcReg = R_00B848_COMPUTE_PGM_RSRC1; break;
  case ShaderType::GEOMETRY: RsrcReg = R_00B228_SPI_SHADER_PGM_RSRC1_GS; break;
  case ShaderType::PIXEL:    RsrcReg = R_00B028_SPI_SHADER_PGM_RSRC1_PS; break;
  case ShaderType::VERTEX:   RsrcReg = R_00B128_SPI_SHADER_PGM_RSRC1_VS; break;
  }

  OutStreamer.EmitIntValue(RsrcReg, 4);
  OutStreamer.EmitIntValue(S_00B028_VGPRS(KernelInfo.NumVGPR / 4) |
                           S_00B028_SGPRS(KernelInfo.NumSGPR / 8), 4);

  unsigned LDSAlignShift;
  if (STM.getGeneration() < AMDGPUSubtarget::SEA_ISLANDS) {
    // LDS is allocated in 64 dword blocks
    LDSAlignShift = 8;
  } else {
    // LDS is allocated in 128 dword blocks
    LDSAlignShift = 9;
  }
  unsigned LDSBlocks =
          RoundUpToAlignment(MFI->LDSSize, 1 << LDSAlignShift) >> LDSAlignShift;

  if (MFI->ShaderType == ShaderType::COMPUTE) {
    OutStreamer.EmitIntValue(R_00B84C_COMPUTE_PGM_RSRC2, 4);
    OutStreamer.EmitIntValue(S_00B84C_LDS_SIZE(LDSBlocks), 4);
  }
  if (MFI->ShaderType == ShaderType::PIXEL) {
    OutStreamer.EmitIntValue(R_00B02C_SPI_SHADER_PGM_RSRC2_PS, 4);
    OutStreamer.EmitIntValue(S_00B02C_EXTRA_LDS_SIZE(LDSBlocks), 4);
    OutStreamer.EmitIntValue(R_0286CC_SPI_PS_INPUT_ENA, 4);
    OutStreamer.EmitIntValue(MFI->PSInputAddr, 4);
  }
}
<|endoftext|>


<commit_before>//===- ValueMapper.cpp - Interface shared by lib/Transforms/Utils ---------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the MapValue function, which is shared by various parts of
// the lib/Transforms/Utils library.
//
//===----------------------------------------------------------------------===//

#include "ValueMapper.h"
#include "llvm/Type.h"
#include "llvm/Constants.h"
#include "llvm/Function.h"
#include "llvm/Metadata.h"
#include "llvm/ADT/SmallVector.h"
using namespace llvm;

Value *llvm::MapValue(const Value *V, ValueToValueMapTy &VM) {
  Value *&VMSlot = VM[V];
  if (VMSlot) return VMSlot;      // Does it exist in the map yet?

  // NOTE: VMSlot can be invalidated by any reference to VM, which can grow the
  // DenseMap.  This includes any recursive calls to MapValue.

  // Global values and non-function-local metadata do not need to be seeded into
  // the ValueMap if they are using the identity mapping.
  if (isa<GlobalValue>(V) || isa<InlineAsm>(V) || isa<MDString>(V) ||
      (isa<MDNode>(V) && !cast<MDNode>(V)->isFunctionLocal()))
    return VMSlot = const_cast<Value*>(V);

  if (const MDNode *MD = dyn_cast<MDNode>(V)) {
    SmallVector<Value*, 4> Elts;
    for (unsigned i = 0, e = MD->getNumOperands(); i != e; ++i)
      Elts.push_back(MD->getOperand(i) ? MapValue(MD->getOperand(i), VM) : 0);
    return VM[V] = MDNode::get(V->getContext(), Elts.data(), Elts.size());
  }

  Constant *C = const_cast<Constant*>(dyn_cast<Constant>(V));
  if (C == 0) return 0;

  if (isa<ConstantInt>(C) || isa<ConstantFP>(C) ||
      isa<ConstantPointerNull>(C) || isa<ConstantAggregateZero>(C) ||
      isa<UndefValue>(C) || isa<MDString>(C))
    return VMSlot = C;           // Primitive constants map directly

  if (ConstantArray *CA = dyn_cast<ConstantArray>(C)) {
    for (User::op_iterator b = CA->op_begin(), i = b, e = CA->op_end();
         i != e; ++i) {
      Value *MV = MapValue(*i, VM);
      if (MV != *i) {
        // This array must contain a reference to a global, make a new array
        // and return it.
        //
        std::vector<Constant*> Values;
        Values.reserve(CA->getNumOperands());
        for (User::op_iterator j = b; j != i; ++j)
          Values.push_back(cast<Constant>(*j));
        Values.push_back(cast<Constant>(MV));
        for (++i; i != e; ++i)
          Values.push_back(cast<Constant>(MapValue(*i, VM)));
        return VM[V] = ConstantArray::get(CA->getType(), Values);
      }
    }
    return VM[V] = C;
  }

  if (ConstantStruct *CS = dyn_cast<ConstantStruct>(C)) {
    for (User::op_iterator b = CS->op_begin(), i = b, e = CS->op_end();
         i != e; ++i) {
      Value *MV = MapValue(*i, VM);
      if (MV != *i) {
        // This struct must contain a reference to a global, make a new struct
        // and return it.
        //
        std::vector<Constant*> Values;
        Values.reserve(CS->getNumOperands());
        for (User::op_iterator j = b; j != i; ++j)
          Values.push_back(cast<Constant>(*j));
        Values.push_back(cast<Constant>(MV));
        for (++i; i != e; ++i)
          Values.push_back(cast<Constant>(MapValue(*i, VM)));
        return VM[V] = ConstantStruct::get(CS->getType(), Values);
      }
    }
    return VM[V] = C;
  }

  if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
    std::vector<Constant*> Ops;
    for (User::op_iterator i = CE->op_begin(), e = CE->op_end(); i != e; ++i)
      Ops.push_back(cast<Constant>(MapValue(*i, VM)));
    return VM[V] = CE->getWithOperands(Ops);
  }

  if (ConstantVector *CV = dyn_cast<ConstantVector>(C)) {
    for (User::op_iterator b = CV->op_begin(), i = b, e = CV->op_end();
         i != e; ++i) {
      Value *MV = MapValue(*i, VM);
      if (MV != *i) {
        // This vector value must contain a reference to a global, make a new
        // vector constant and return it.
        //
        std::vector<Constant*> Values;
        Values.reserve(CV->getNumOperands());
        for (User::op_iterator j = b; j != i; ++j)
          Values.push_back(cast<Constant>(*j));
        Values.push_back(cast<Constant>(MV));
        for (++i; i != e; ++i)
          Values.push_back(cast<Constant>(MapValue(*i, VM)));
        return VM[V] = ConstantVector::get(Values);
      }
    }
    return VM[V] = C;
  }

  BlockAddress *BA = cast<BlockAddress>(C);
  Function *F = cast<Function>(MapValue(BA->getFunction(), VM));
  BasicBlock *BB = cast_or_null<BasicBlock>(MapValue(BA->getBasicBlock(),VM));
  return VM[V] = BlockAddress::get(F, BB ? BB : BA->getBasicBlock());
}

/// RemapInstruction - Convert the instruction operands from referencing the
/// current values into those specified by ValueMap.
///
void llvm::RemapInstruction(Instruction *I, ValueToValueMapTy &ValueMap) {
  for (User::op_iterator op = I->op_begin(), E = I->op_end(); op != E; ++op) {
    Value *V = MapValue(*op, ValueMap);
    assert(V && "Referenced value not in value map!");
    *op = V;
  }
}

<commit_msg>If a metadata operand is seeded in value map and the metadata should also be seeded in value map. This is not limited to function local metadata. <commit_after>//===- ValueMapper.cpp - Interface shared by lib/Transforms/Utils ---------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the MapValue function, which is shared by various parts of
// the lib/Transforms/Utils library.
//
//===----------------------------------------------------------------------===//

#include "ValueMapper.h"
#include "llvm/Type.h"
#include "llvm/Constants.h"
#include "llvm/Function.h"
#include "llvm/Metadata.h"
#include "llvm/ADT/SmallVector.h"
using namespace llvm;

Value *llvm::MapValue(const Value *V, ValueToValueMapTy &VM) {
  ValueToValueMapTy::iterator VMI = VM.find(V);
  if (VMI != VM.end())
    return VMI->second;      // Does it exist in the map yet?

  // Global values, metadata strings and inline asm do not need to be seeded into
  // the ValueMap if they are using the identity mapping.
  if (isa<GlobalValue>(V) || isa<InlineAsm>(V) || isa<MDString>(V)) {
    VM.insert(std::make_pair(V, const_cast<Value*>(V)));
    return const_cast<Value*>(V);
  }

  if (const MDNode *MD = dyn_cast<MDNode>(V)) {
    // Insert a place holder in map to handle mdnode cycles.
    Value *TmpV = MDString::get(V->getContext(),
                                std::string("llvm.md.clone.tmp." + VM.size()));
    VM.insert(std::make_pair(V, MDNode::get(V->getContext(), &TmpV, 1)));

    bool ReuseMD = true;
    SmallVector<Value*, 4> Elts;
    // If metadata element is mapped to a new value then seed metadata
    // in the map.
    for (unsigned i = 0, e = MD->getNumOperands(); i != e; ++i) {
      if (!MD->getOperand(i))
        Elts.push_back(0);
      else {
        Value *MappedOp = MapValue(MD->getOperand(i), VM);
        if (MappedOp != MD->getOperand(i))
          ReuseMD = false;
        Elts.push_back(MappedOp);
      }
    }
    if (ReuseMD) {
      VM.insert(std::make_pair(V, const_cast<Value*>(V)));
      return const_cast<Value*>(V);
    }
    MDNode *NewMD = MDNode::get(V->getContext(), Elts.data(), Elts.size());
    VM.insert(std::make_pair(V, NewMD));
    return NewMD;
  }

  Constant *C = const_cast<Constant*>(dyn_cast<Constant>(V));
  if (C == 0) return 0;

  if (isa<ConstantInt>(C) || isa<ConstantFP>(C) ||
      isa<ConstantPointerNull>(C) || isa<ConstantAggregateZero>(C) ||
      isa<UndefValue>(C) || isa<MDString>(C))
    return VM[V] = C;           // Primitive constants map directly

  if (ConstantArray *CA = dyn_cast<ConstantArray>(C)) {
    for (User::op_iterator b = CA->op_begin(), i = b, e = CA->op_end();
         i != e; ++i) {
      Value *MV = MapValue(*i, VM);
      if (MV != *i) {
        // This array must contain a reference to a global, make a new array
        // and return it.
        //
        std::vector<Constant*> Values;
        Values.reserve(CA->getNumOperands());
        for (User::op_iterator j = b; j != i; ++j)
          Values.push_back(cast<Constant>(*j));
        Values.push_back(cast<Constant>(MV));
        for (++i; i != e; ++i)
          Values.push_back(cast<Constant>(MapValue(*i, VM)));
        return VM[V] = ConstantArray::get(CA->getType(), Values);
      }
    }
    return VM[V] = C;
  }

  if (ConstantStruct *CS = dyn_cast<ConstantStruct>(C)) {
    for (User::op_iterator b = CS->op_begin(), i = b, e = CS->op_end();
         i != e; ++i) {
      Value *MV = MapValue(*i, VM);
      if (MV != *i) {
        // This struct must contain a reference to a global, make a new struct
        // and return it.
        //
        std::vector<Constant*> Values;
        Values.reserve(CS->getNumOperands());
        for (User::op_iterator j = b; j != i; ++j)
          Values.push_back(cast<Constant>(*j));
        Values.push_back(cast<Constant>(MV));
        for (++i; i != e; ++i)
          Values.push_back(cast<Constant>(MapValue(*i, VM)));
        return VM[V] = ConstantStruct::get(CS->getType(), Values);
      }
    }
    return VM[V] = C;
  }

  if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
    std::vector<Constant*> Ops;
    for (User::op_iterator i = CE->op_begin(), e = CE->op_end(); i != e; ++i)
      Ops.push_back(cast<Constant>(MapValue(*i, VM)));
    return VM[V] = CE->getWithOperands(Ops);
  }

  if (ConstantVector *CV = dyn_cast<ConstantVector>(C)) {
    for (User::op_iterator b = CV->op_begin(), i = b, e = CV->op_end();
         i != e; ++i) {
      Value *MV = MapValue(*i, VM);
      if (MV != *i) {
        // This vector value must contain a reference to a global, make a new
        // vector constant and return it.
        //
        std::vector<Constant*> Values;
        Values.reserve(CV->getNumOperands());
        for (User::op_iterator j = b; j != i; ++j)
          Values.push_back(cast<Constant>(*j));
        Values.push_back(cast<Constant>(MV));
        for (++i; i != e; ++i)
          Values.push_back(cast<Constant>(MapValue(*i, VM)));
        return VM[V] = ConstantVector::get(Values);
      }
    }
    return VM[V] = C;
  }

  BlockAddress *BA = cast<BlockAddress>(C);
  Function *F = cast<Function>(MapValue(BA->getFunction(), VM));
  BasicBlock *BB = cast_or_null<BasicBlock>(MapValue(BA->getBasicBlock(),VM));
  return VM[V] = BlockAddress::get(F, BB ? BB : BA->getBasicBlock());
}

/// RemapInstruction - Convert the instruction operands from referencing the
/// current values into those specified by ValueMap.
///
void llvm::RemapInstruction(Instruction *I, ValueToValueMapTy &ValueMap) {
  for (User::op_iterator op = I->op_begin(), E = I->op_end(); op != E; ++op) {
    Value *V = MapValue(*op, ValueMap);
    assert(V && "Referenced value not in value map!");
    *op = V;
  }
}

<|endoftext|>


<commit_before>#include <QtCore/qmath.h>
#include <utils/RgbTransform.h>

RgbTransform::RgbTransform()
{
	init(1.0, 1.0, 1.0, 0.0, false, 100, 100);
}

RgbTransform::RgbTransform(double gammaR, double gammaG, double gammaB, double backlightThreshold, bool backlightColored, uint8_t brightness, uint8_t brightnessCompensation)
{
	init(gammaR, gammaG, gammaB, backlightThreshold, backlightColored, brightness, brightnessCompensation);
}

void RgbTransform::init(double gammaR, double gammaG, double gammaB, double backlightThreshold, bool backlightColored, uint8_t brightness, uint8_t brightnessCompensation)
{
	_backLightEnabled = true;
	setGamma(gammaR,gammaG,gammaB);
	setBacklightThreshold(backlightThreshold);
	setBacklightColored(backlightColored);
	setBrightness(brightness);
	setBrightnessCompensation(brightnessCompensation);
	initializeMapping();
}

RgbTransform::~RgbTransform()
{
}

double RgbTransform::getGammaR() const
{
	return _gammaR;
}

double RgbTransform::getGammaG() const
{
	return _gammaG;
}

double RgbTransform::getGammaB() const
{
	return _gammaB;
}

void RgbTransform::setGamma(double gammaR, double gammaG, double gammaB)
{
	_gammaR = gammaR;
	_gammaG = (gammaG < 0.0) ? _gammaR : gammaG;
	_gammaB = (gammaB < 0.0) ? _gammaR : gammaB;
	initializeMapping();
}

void RgbTransform::initializeMapping()
{
	for (int i = 0; i < 256; ++i)
	{
		_mappingR[i] = qMin(qMax((int)(qPow(i / 255.0, _gammaR) * 255), 0), 255);
		_mappingG[i] = qMin(qMax((int)(qPow(i / 255.0, _gammaG) * 255), 0), 255);
		_mappingB[i] = qMin(qMax((int)(qPow(i / 255.0, _gammaB) * 255), 0), 255);
	}
}

int RgbTransform::getBacklightThreshold() const
{
	return _backlightThreshold;
}

void RgbTransform::setBacklightThreshold(int backlightThreshold)
{
	_backlightThreshold = backlightThreshold;
	_sumBrightnessLow   = 765.0 * ((qPow(2.0,(_backlightThreshold/100)*2)-1) / 3.0);
}

bool RgbTransform::getBacklightColored() const
{
	return _backlightColored;
}

void RgbTransform::setBacklightColored(bool backlightColored)
{
	_backlightColored = backlightColored;
}

bool RgbTransform::getBackLightEnabled() const
{
	return _backLightEnabled;
}

void RgbTransform::setBackLightEnabled(bool enable)
{
	_backLightEnabled = enable;
}

uint8_t RgbTransform::getBrightness() const
{
	return _brightness;
}

void RgbTransform::setBrightness(uint8_t brightness)
{
	_brightness    = brightness;
	updateBrightnessComponents();
}

void RgbTransform::setBrightnessCompensation(uint8_t brightnessCompensation)
{
	_brightnessCompensation = brightnessCompensation;
	updateBrightnessComponents();
}

uint8_t RgbTransform::getBrightnessCompensation() const
{
	return _brightnessCompensation;
}

void RgbTransform::updateBrightnessComponents()
{
	double Fw   = _brightnessCompensation*2.0/100.0+1.0;
	double Fcmy = _brightnessCompensation/100.0+1.0;

	double B_in= 0;
	_brightness_rgb = 0;
	_brightness_cmy = 0;
	_brightness_w   = 0;

	if (_brightness > 0)
	{
		B_in = (_brightness<50)? -0.09*_brightness+7.5 : -0.04*_brightness+5.0;

		_brightness_rgb = std::ceil(qMin(255.0,255.0/B_in));
		_brightness_cmy = std::ceil(qMin(255.0,255.0/(B_in*Fcmy)));
		_brightness_w   = std::ceil(qMin(255.0,255.0/(B_in*Fw)));
	}
}

void RgbTransform::getBrightnessComponents(uint8_t & rgb, uint8_t & cmy, uint8_t & w )
{
	rgb = _brightness_rgb;
	cmy = _brightness_cmy;
	w   = _brightness_w;
}

void RgbTransform::transform(uint8_t & red, uint8_t & green, uint8_t & blue)
{
	// apply gamma
	red   = _mappingR[red];
	green = _mappingR[green];
	blue  = _mappingR[blue];

	// apply brightnesss
	int rgbSum = red+green+blue;

	if ( _backLightEnabled && _sumBrightnessLow>0 && rgbSum < _sumBrightnessLow)
	{
		if (_backlightColored)
		{
			if (rgbSum == 0)
			{
				if (red  ==0) red   = 1;
				if (green==0) green = 1;
				if (blue ==0) blue  = 1;
				rgbSum = red+green+blue;
			}
			double cL =qMin((int)(_sumBrightnessLow /rgbSum), 255);

			red   *= cL;
			green *= cL;
			blue  *= cL;
		}
		else
		{
			red   = qMin((int)(_sumBrightnessLow/3.0), 255);
			green = red;
			blue  = red;
		}
	}
}

<commit_msg>RGBTransform fix gamma adjustment of green, blue always taking red value<commit_after>#include <QtCore/qmath.h>
#include <utils/RgbTransform.h>

RgbTransform::RgbTransform()
{
	init(1.0, 1.0, 1.0, 0.0, false, 100, 100);
}

RgbTransform::RgbTransform(double gammaR, double gammaG, double gammaB, double backlightThreshold, bool backlightColored, uint8_t brightness, uint8_t brightnessCompensation)
{
	init(gammaR, gammaG, gammaB, backlightThreshold, backlightColored, brightness, brightnessCompensation);
}

void RgbTransform::init(double gammaR, double gammaG, double gammaB, double backlightThreshold, bool backlightColored, uint8_t brightness, uint8_t brightnessCompensation)
{
	_backLightEnabled = true;
	setGamma(gammaR,gammaG,gammaB);
	setBacklightThreshold(backlightThreshold);
	setBacklightColored(backlightColored);
	setBrightness(brightness);
	setBrightnessCompensation(brightnessCompensation);
	initializeMapping();
}

RgbTransform::~RgbTransform()
{
}

double RgbTransform::getGammaR() const
{
	return _gammaR;
}

double RgbTransform::getGammaG() const
{
	return _gammaG;
}

double RgbTransform::getGammaB() const
{
	return _gammaB;
}

void RgbTransform::setGamma(double gammaR, double gammaG, double gammaB)
{
	_gammaR = gammaR;
	_gammaG = (gammaG < 0.0) ? _gammaR : gammaG;
	_gammaB = (gammaB < 0.0) ? _gammaR : gammaB;
	initializeMapping();
}

void RgbTransform::initializeMapping()
{
	for (int i = 0; i < 256; ++i)
	{
		_mappingR[i] = qMin(qMax((int)(qPow(i / 255.0, _gammaR) * 255), 0), 255);
		_mappingG[i] = qMin(qMax((int)(qPow(i / 255.0, _gammaG) * 255), 0), 255);
		_mappingB[i] = qMin(qMax((int)(qPow(i / 255.0, _gammaB) * 255), 0), 255);
	}
}

int RgbTransform::getBacklightThreshold() const
{
	return _backlightThreshold;
}

void RgbTransform::setBacklightThreshold(int backlightThreshold)
{
	_backlightThreshold = backlightThreshold;
	_sumBrightnessLow   = 765.0 * ((qPow(2.0,(_backlightThreshold/100)*2)-1) / 3.0);
}

bool RgbTransform::getBacklightColored() const
{
	return _backlightColored;
}

void RgbTransform::setBacklightColored(bool backlightColored)
{
	_backlightColored = backlightColored;
}

bool RgbTransform::getBackLightEnabled() const
{
	return _backLightEnabled;
}

void RgbTransform::setBackLightEnabled(bool enable)
{
	_backLightEnabled = enable;
}

uint8_t RgbTransform::getBrightness() const
{
	return _brightness;
}

void RgbTransform::setBrightness(uint8_t brightness)
{
	_brightness    = brightness;
	updateBrightnessComponents();
}

void RgbTransform::setBrightnessCompensation(uint8_t brightnessCompensation)
{
	_brightnessCompensation = brightnessCompensation;
	updateBrightnessComponents();
}

uint8_t RgbTransform::getBrightnessCompensation() const
{
	return _brightnessCompensation;
}

void RgbTransform::updateBrightnessComponents()
{
	double Fw   = _brightnessCompensation*2.0/100.0+1.0;
	double Fcmy = _brightnessCompensation/100.0+1.0;

	double B_in= 0;
	_brightness_rgb = 0;
	_brightness_cmy = 0;
	_brightness_w   = 0;

	if (_brightness > 0)
	{
		B_in = (_brightness<50)? -0.09*_brightness+7.5 : -0.04*_brightness+5.0;

		_brightness_rgb = std::ceil(qMin(255.0,255.0/B_in));
		_brightness_cmy = std::ceil(qMin(255.0,255.0/(B_in*Fcmy)));
		_brightness_w   = std::ceil(qMin(255.0,255.0/(B_in*Fw)));
	}
}

void RgbTransform::getBrightnessComponents(uint8_t & rgb, uint8_t & cmy, uint8_t & w )
{
	rgb = _brightness_rgb;
	cmy = _brightness_cmy;
	w   = _brightness_w;
}

void RgbTransform::transform(uint8_t & red, uint8_t & green, uint8_t & blue)
{
	// apply gamma
	red   = _mappingR[red];
	green = _mappingG[green];
	blue  = _mappingB[blue];

	// apply brightnesss
	int rgbSum = red+green+blue;

	if ( _backLightEnabled && _sumBrightnessLow>0 && rgbSum < _sumBrightnessLow)
	{
		if (_backlightColored)
		{
			if (rgbSum == 0)
			{
				if (red  ==0) red   = 1;
				if (green==0) green = 1;
				if (blue ==0) blue  = 1;
				rgbSum = red+green+blue;
			}
			double cL =qMin((int)(_sumBrightnessLow /rgbSum), 255);

			red   *= cL;
			green *= cL;
			blue  *= cL;
		}
		else
		{
			red   = qMin((int)(_sumBrightnessLow/3.0), 255);
			green = red;
			blue  = red;
		}
	}
}

<|endoftext|>


<commit_before>// python2/3 module for tinyobjloader
//
// usage:
// import tinyobjloader as tol
// model = tol.LoadObj(name)
// print(model["shapes"])
// print(model["materials"]
// note:
//   `shape.mesh.index_t` is represented as flattened array: (vertex_index, normal_index, texcoord_index) * num_faces

#include <Python.h>
#include <vector>
#include "../tiny_obj_loader.h"

typedef std::vector<double> vectd;
typedef std::vector<int> vecti;

PyObject* pyTupleFromfloat3(float array[3]) {
  int i;
  PyObject* tuple = PyTuple_New(3);

  for (i = 0; i <= 2; i++) {
    PyTuple_SetItem(tuple, i, PyFloat_FromDouble(array[i]));
  }

  return tuple;
}

extern "C" {

static PyObject* pyLoadObj(PyObject* self, PyObject* args) {
  PyObject *rtndict, *pyshapes, *pymaterials, *pymaterial_indices, *attribobj, *current, *meshobj;

  char const* current_name;
  char const* filename;
  vectd vect;
  std::vector<tinyobj::index_t> indices;
  std::vector<unsigned char> face_verts;

  tinyobj::attrib_t attrib;
  std::vector<tinyobj::shape_t> shapes;
  std::vector<tinyobj::material_t> materials;

  if (!PyArg_ParseTuple(args, "s", &filename)) return NULL;

  std::string err;
  tinyobj::LoadObj(&attrib, &shapes, &materials, &err, filename);

  pyshapes = PyDict_New();
  pymaterials = PyDict_New();
  pymaterial_indices = PyDict_New();
  rtndict = PyDict_New();

  attribobj = PyDict_New();

  for (int i = 0; i <= 2; i++) {
    current = PyList_New(0);

    switch (i) {
      case 0:
        current_name = "vertices";
        vect = vectd(attrib.vertices.begin(), attrib.vertices.end());
        break;
      case 1:
        current_name = "normals";
        vect = vectd(attrib.normals.begin(), attrib.normals.end());
        break;
      case 2:
        current_name = "texcoords";
        vect = vectd(attrib.texcoords.begin(), attrib.texcoords.end());
        break;
    }

    for (vectd::iterator it = vect.begin(); it != vect.end(); it++) {
      PyList_Insert(current, it - vect.begin(), PyFloat_FromDouble(*it));
    }

    PyDict_SetItemString(attribobj, current_name, current);
  }

  for (std::vector<tinyobj::shape_t>::iterator shape = shapes.begin();
       shape != shapes.end(); shape++) {
    meshobj = PyDict_New();
    tinyobj::mesh_t cm = (*shape).mesh;

    {
      current = PyList_New(0);

      for (size_t i = 0; i < cm.indices.size(); i++) {
        // Flatten index array: v_idx, vn_idx, vt_idx, v_idx, vn_idx, vt_idx,
        // ...
        PyList_Insert(current, 3 * i + 0,
                      PyLong_FromLong(cm.indices[i].vertex_index));
        PyList_Insert(current, 3 * i + 1,
                      PyLong_FromLong(cm.indices[i].normal_index));
        PyList_Insert(current, 3 * i + 2,
                      PyLong_FromLong(cm.indices[i].texcoord_index));
      }

      PyDict_SetItemString(meshobj, "indices", current);
    }

    {
      current = PyList_New(0);

      for (size_t i = 0; i < cm.num_face_vertices.size(); i++) {
        // Widen data type to long.
        PyList_Insert(current, i, PyLong_FromLong(cm.num_face_vertices[i]));
      }

      PyDict_SetItemString(meshobj, "num_face_vertices", current);
    }

    {
      current = PyList_New(0);

      for (size_t i = 0; i < cm.material_ids.size(); i++) {
        PyList_Insert(current, i, PyLong_FromLong(cm.material_ids[i]));
      }

      PyDict_SetItemString(meshobj, "material_ids", current);
    }

    PyDict_SetItemString(pyshapes, (*shape).name.c_str(), meshobj);
  }

  long material_index = 0;
  for (std::vector<tinyobj::material_t>::iterator mat = materials.begin();
       mat != materials.end(); mat++) {
    PyObject* matobj = PyDict_New();
    PyObject* unknown_parameter = PyDict_New();

    for (std::map<std::string, std::string>::iterator p =
             (*mat).unknown_parameter.begin();
         p != (*mat).unknown_parameter.end(); ++p) {
      PyDict_SetItemString(unknown_parameter, p->first.c_str(),
                           PyUnicode_FromString(p->second.c_str()));
    }

    PyDict_SetItemString(matobj, "shininess",
                         PyFloat_FromDouble((*mat).shininess));
    PyDict_SetItemString(matobj, "ior", PyFloat_FromDouble((*mat).ior));
    PyDict_SetItemString(matobj, "dissolve",
                         PyFloat_FromDouble((*mat).dissolve));
    PyDict_SetItemString(matobj, "illum", PyLong_FromLong((*mat).illum));
    PyDict_SetItemString(matobj, "ambient_texname",
                         PyUnicode_FromString((*mat).ambient_texname.c_str()));
    PyDict_SetItemString(matobj, "diffuse_texname",
                         PyUnicode_FromString((*mat).diffuse_texname.c_str()));
    PyDict_SetItemString(matobj, "specular_texname",
                         PyUnicode_FromString((*mat).specular_texname.c_str()));
    PyDict_SetItemString(
        matobj, "specular_highlight_texname",
        PyUnicode_FromString((*mat).specular_highlight_texname.c_str()));
    PyDict_SetItemString(matobj, "bump_texname",
                         PyUnicode_FromString((*mat).bump_texname.c_str()));
    PyDict_SetItemString(
        matobj, "displacement_texname",
        PyUnicode_FromString((*mat).displacement_texname.c_str()));
    PyDict_SetItemString(matobj, "alpha_texname",
                         PyUnicode_FromString((*mat).alpha_texname.c_str()));
    PyDict_SetItemString(matobj, "ambient", pyTupleFromfloat3((*mat).ambient));
    PyDict_SetItemString(matobj, "diffuse", pyTupleFromfloat3((*mat).diffuse));
    PyDict_SetItemString(matobj, "specular",
                         pyTupleFromfloat3((*mat).specular));
    PyDict_SetItemString(matobj, "transmittance",
                         pyTupleFromfloat3((*mat).transmittance));
    PyDict_SetItemString(matobj, "emission",
                         pyTupleFromfloat3((*mat).emission));
    PyDict_SetItemString(matobj, "unknown_parameter", unknown_parameter);

    PyDict_SetItemString(pymaterials, (*mat).name.c_str(), matobj);
    PyDict_SetItemString(pymaterial_indices, PyLong_FromLong(material_index++), (*mat).name.c_str());
  }

  PyDict_SetItemString(rtndict, "shapes", pyshapes);
  PyDict_SetItemString(rtndict, "materials", pymaterials);
  PyDict_SetItemString(rtndict, "material_indices", pymaterial_indices);
  PyDict_SetItemString(rtndict, "attribs", attribobj);

  return rtndict;
}

static PyMethodDef mMethods[] = {

    {"LoadObj", pyLoadObj, METH_VARARGS}, {NULL, NULL, 0, NULL}

};

#if PY_MAJOR_VERSION >= 3

static struct PyModuleDef moduledef = {PyModuleDef_HEAD_INIT, "tinyobjloader",
                                       NULL, -1, mMethods};

PyMODINIT_FUNC PyInit_tinyobjloader(void) {
  return PyModule_Create(&moduledef);
}

#else

PyMODINIT_FUNC inittinyobjloader(void) {
  Py_InitModule3("tinyobjloader", mMethods, NULL);
}

#endif  // PY_MAJOR_VERSION >= 3

}
<commit_msg>Fix mapping for #131 and compilation error #139 #132 (related)<commit_after>// python2/3 module for tinyobjloader
//
// usage:
// import tinyobjloader as tol
// model = tol.LoadObj(name)
// print(model["shapes"])
// print(model["materials"]
// note:
//   `shape.mesh.index_t` is represented as flattened array: (vertex_index, normal_index, texcoord_index) * num_faces

#include <Python.h>
#include <vector>
#include "../tiny_obj_loader.h"

typedef std::vector<double> vectd;
typedef std::vector<int> vecti;

PyObject* pyTupleFromfloat3(float array[3]) {
  int i;
  PyObject* tuple = PyTuple_New(3);

  for (i = 0; i <= 2; i++) {
    PyTuple_SetItem(tuple, i, PyFloat_FromDouble(array[i]));
  }

  return tuple;
}

extern "C" {

static PyObject* pyLoadObj(PyObject* self, PyObject* args) {
  PyObject *rtndict, *pyshapes, *pymaterials, *pymaterial_indices, *attribobj, *current, *meshobj;

  char const* current_name;
  char const* filename;
  vectd vect;
  std::vector<tinyobj::index_t> indices;
  std::vector<unsigned char> face_verts;

  tinyobj::attrib_t attrib;
  std::vector<tinyobj::shape_t> shapes;
  std::vector<tinyobj::material_t> materials;

  if (!PyArg_ParseTuple(args, "s", &filename)) return NULL;

  std::string err;
  tinyobj::LoadObj(&attrib, &shapes, &materials, &err, filename);

  pyshapes = PyDict_New();
  pymaterials = PyDict_New();
  pymaterial_indices = PyList_New(0);
  rtndict = PyDict_New();

  attribobj = PyDict_New();

  for (int i = 0; i <= 2; i++) {
    current = PyList_New(0);

    switch (i) {
      case 0:
        current_name = "vertices";
        vect = vectd(attrib.vertices.begin(), attrib.vertices.end());
        break;
      case 1:
        current_name = "normals";
        vect = vectd(attrib.normals.begin(), attrib.normals.end());
        break;
      case 2:
        current_name = "texcoords";
        vect = vectd(attrib.texcoords.begin(), attrib.texcoords.end());
        break;
    }

    for (vectd::iterator it = vect.begin(); it != vect.end(); it++) {
      PyList_Insert(current, it - vect.begin(), PyFloat_FromDouble(*it));
    }

    PyDict_SetItemString(attribobj, current_name, current);
  }

  for (std::vector<tinyobj::shape_t>::iterator shape = shapes.begin();
       shape != shapes.end(); shape++) {
    meshobj = PyDict_New();
    tinyobj::mesh_t cm = (*shape).mesh;

    {
      current = PyList_New(0);

      for (size_t i = 0; i < cm.indices.size(); i++) {
        // Flatten index array: v_idx, vn_idx, vt_idx, v_idx, vn_idx, vt_idx,
        // ...
        PyList_Insert(current, 3 * i + 0,
                      PyLong_FromLong(cm.indices[i].vertex_index));
        PyList_Insert(current, 3 * i + 1,
                      PyLong_FromLong(cm.indices[i].normal_index));
        PyList_Insert(current, 3 * i + 2,
                      PyLong_FromLong(cm.indices[i].texcoord_index));
      }

      PyDict_SetItemString(meshobj, "indices", current);
    }

    {
      current = PyList_New(0);

      for (size_t i = 0; i < cm.num_face_vertices.size(); i++) {
        // Widen data type to long.
        PyList_Insert(current, i, PyLong_FromLong(cm.num_face_vertices[i]));
      }

      PyDict_SetItemString(meshobj, "num_face_vertices", current);
    }

    {
      current = PyList_New(0);

      for (size_t i = 0; i < cm.material_ids.size(); i++) {
        PyList_Insert(current, i, PyLong_FromLong(cm.material_ids[i]));
      }

      PyDict_SetItemString(meshobj, "material_ids", current);
    }

    PyDict_SetItemString(pyshapes, (*shape).name.c_str(), meshobj);
  }

  for (std::vector<tinyobj::material_t>::iterator mat = materials.begin();
       mat != materials.end(); mat++) {
    PyObject* matobj = PyDict_New();
    PyObject* unknown_parameter = PyDict_New();

    for (std::map<std::string, std::string>::iterator p =
             mat->unknown_parameter.begin();
         p != mat->unknown_parameter.end(); ++p) {
      PyDict_SetItemString(unknown_parameter, p->first.c_str(),
                           PyUnicode_FromString(p->second.c_str()));
    }

    PyDict_SetItemString(matobj, "shininess",
                         PyFloat_FromDouble(mat->shininess));
    PyDict_SetItemString(matobj, "ior", PyFloat_FromDouble(mat->ior));
    PyDict_SetItemString(matobj, "dissolve",
                         PyFloat_FromDouble(mat->dissolve));
    PyDict_SetItemString(matobj, "illum", PyLong_FromLong(mat->illum));
    PyDict_SetItemString(matobj, "ambient_texname",
                         PyUnicode_FromString(mat->ambient_texname.c_str()));
    PyDict_SetItemString(matobj, "diffuse_texname",
                         PyUnicode_FromString(mat->diffuse_texname.c_str()));
    PyDict_SetItemString(matobj, "specular_texname",
                         PyUnicode_FromString(mat->specular_texname.c_str()));
    PyDict_SetItemString(
        matobj, "specular_highlight_texname",
        PyUnicode_FromString(mat->specular_highlight_texname.c_str()));
    PyDict_SetItemString(matobj, "bump_texname",
                         PyUnicode_FromString(mat->bump_texname.c_str()));
    PyDict_SetItemString(
        matobj, "displacement_texname",
        PyUnicode_FromString(mat->displacement_texname.c_str()));
    PyDict_SetItemString(matobj, "alpha_texname",
                         PyUnicode_FromString(mat->alpha_texname.c_str()));
    PyDict_SetItemString(matobj, "ambient", pyTupleFromfloat3(mat->ambient));
    PyDict_SetItemString(matobj, "diffuse", pyTupleFromfloat3(mat->diffuse));
    PyDict_SetItemString(matobj, "specular",
                         pyTupleFromfloat3(mat->specular));
    PyDict_SetItemString(matobj, "transmittance",
                         pyTupleFromfloat3(mat->transmittance));
    PyDict_SetItemString(matobj, "emission",
                         pyTupleFromfloat3(mat->emission));
    PyDict_SetItemString(matobj, "unknown_parameter", unknown_parameter);

    PyDict_SetItemString(pymaterials, mat->name.c_str(), matobj);
    PyList_Append(pymaterial_indices, PyUnicode_FromString(mat->name.c_str()));
  }

  PyDict_SetItemString(rtndict, "shapes", pyshapes);
  PyDict_SetItemString(rtndict, "materials", pymaterials);
  PyDict_SetItemString(rtndict, "material_indices", pymaterial_indices);
  PyDict_SetItemString(rtndict, "attribs", attribobj);

  return rtndict;
}

static PyMethodDef mMethods[] = {

    {"LoadObj", pyLoadObj, METH_VARARGS}, {NULL, NULL, 0, NULL}

};

#if PY_MAJOR_VERSION >= 3

static struct PyModuleDef moduledef = {PyModuleDef_HEAD_INIT, "tinyobjloader",
                                       NULL, -1, mMethods};

PyMODINIT_FUNC PyInit_tinyobjloader(void) {
  return PyModule_Create(&moduledef);
}

#else

PyMODINIT_FUNC inittinyobjloader(void) {
  Py_InitModule3("tinyobjloader", mMethods, NULL);
}

#endif  // PY_MAJOR_VERSION >= 3

}
<|endoftext|>


<commit_before>/*
 * Copyright 2015 Cloudius Systems
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1
#include <cryptopp/md5.h>
#include "bytes_ostream.hh"
#include "query-request.hh"
#include "db/serializer.hh"

namespace query {

class result_digest {
    bytes _digest;
public:
    result_digest(bytes&& digest) : _digest(std::move(digest)) {}
    const bytes& get() const { return _digest; }
    bool operator==(const result_digest& rh) const {
        return _digest == rh._digest;
    }
    bool operator!=(const result_digest& rh) const {
        return _digest != rh._digest;
    }
    size_t serialized_size() const { return _digest.size(); }
    void serialize(bytes::iterator& out) const {
        out = std::copy(_digest.begin(), _digest.end(), out);
    }
    static result_digest deserialize(bytes_view& in) {
        auto result = result_digest(bytes(in.begin(), in.end()));
        in.remove_prefix(in.size());
        return result;
    }
};

//
// The query results are stored in a serialized form. This is in order to
// address the following problems, which a structured format has:
//
//   - high level of indirection (vector of vectors of vectors of blobs), which
//     is not CPU cache friendly
//
//   - high allocation rate due to fine-grained object structure
//
// On replica side, the query results are probably going to be serialized in
// the transport layer anyway, so serializing the results up-front doesn't add
// net work. There is no processing of the query results on replica other than
// concatenation in case of range queries and checksum calculation. If query
// results are collected in serialized form from different cores, we can
// concatenate them without copying by simply appending the fragments into the
// packet.
//
// On coordinator side, the query results would have to be parsed from the
// transport layer buffers anyway, so the fact that iterators parse it also
// doesn't add net work, but again saves allocations and copying. The CQL
// server doesn't need complex data structures to process the results, it just
// goes over it linearly consuming it.
//
// The coordinator side could be optimized even further for CQL queries which
// do not need processing (eg. select * from cf where ...). We could make the
// replica send the query results in the format which is expected by the CQL
// binary protocol client. So in the typical case the coordinator would just
// pass the data using zero-copy to the client, prepending a header.
//
// Users which need more complex structure of query results, should
// transform it to such using appropriate visitors.
// TODO: insert reference to such visitors here.
//
// Query results have dynamic format. In some queries (maybe even in typical
// ones), we don't need to send partition or clustering keys back to the
// client, because they are already specified in the query request, and not
// queried for. The query results hold keys optionally.
//
// Also, meta-data like cell timestamp and expiry is optional. It is only needed
// if the query has writetime() or ttl() functions in it, which it typically
// won't have.
//
// Related headers:
//  - query-result-reader.hh
//  - query-result-writer.hh

//
// Query results are serialized to the following form:
//
// <result>          ::= <partition>*
// <partition>       ::= <row-count> [ <partition-key> ] [ <static-row> ] <row>*
// <static-row>      ::= <row>
// <row>             ::= <row-length> <cell>+
// <cell>            ::= <atomic-cell> | <collection-cell>
// <atomic-cell>     ::= <present-byte> [ <timestamp> <expiry> ] <value>
// <collection-cell> ::= <blob>
//
// <value>           ::= <blob>
// <blob>            ::= <blob-length> <uint8_t>*
// <timestamp>       ::= <uint64_t>
// <expiry>          ::= <int32_t>
// <present-byte>    ::= <int8_t>
// <row-length>      ::= <uint32_t>
// <row-count>       ::= <uint32_t>
// <blob-length>     ::= <uint32_t>
//
class result {
    bytes_ostream _w;
public:
    class builder;
    class partition_writer;
    class row_writer;
    friend class result_merger;

    result() {}
    result(bytes_ostream&& w) : _w(std::move(w)) {}
    result(result&&) = default;
    result(const result&) = default;
    result& operator=(result&&) = default;
    result& operator=(const result&) = default;

    const bytes_ostream& buf() const {
        return _w;
    }

    result_digest digest() {
        CryptoPP::Weak::MD5 hash;
        bytes b(bytes::initialized_later(), CryptoPP::Weak::MD5::DIGESTSIZE);
        bytes_view v = _w.linearize();
        hash.CalculateDigest(reinterpret_cast<unsigned char*>(b.begin()), reinterpret_cast<const unsigned char*>(v.begin()), v.size());
        return result_digest(std::move(b));
    }
    sstring pretty_print(schema_ptr, const query::partition_slice&) const;
};

}
<commit_msg>Remove old result_digest serializer<commit_after>/*
 * Copyright 2015 Cloudius Systems
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1
#include <cryptopp/md5.h>
#include "bytes_ostream.hh"
#include "query-request.hh"
#include "db/serializer.hh"

namespace query {

class result_digest {
    bytes _digest;
public:
    result_digest(bytes&& digest) : _digest(std::move(digest)) {}
    const bytes& get() const { return _digest; }
    bool operator==(const result_digest& rh) const {
        return _digest == rh._digest;
    }
    bool operator!=(const result_digest& rh) const {
        return _digest != rh._digest;
    }
};

//
// The query results are stored in a serialized form. This is in order to
// address the following problems, which a structured format has:
//
//   - high level of indirection (vector of vectors of vectors of blobs), which
//     is not CPU cache friendly
//
//   - high allocation rate due to fine-grained object structure
//
// On replica side, the query results are probably going to be serialized in
// the transport layer anyway, so serializing the results up-front doesn't add
// net work. There is no processing of the query results on replica other than
// concatenation in case of range queries and checksum calculation. If query
// results are collected in serialized form from different cores, we can
// concatenate them without copying by simply appending the fragments into the
// packet.
//
// On coordinator side, the query results would have to be parsed from the
// transport layer buffers anyway, so the fact that iterators parse it also
// doesn't add net work, but again saves allocations and copying. The CQL
// server doesn't need complex data structures to process the results, it just
// goes over it linearly consuming it.
//
// The coordinator side could be optimized even further for CQL queries which
// do not need processing (eg. select * from cf where ...). We could make the
// replica send the query results in the format which is expected by the CQL
// binary protocol client. So in the typical case the coordinator would just
// pass the data using zero-copy to the client, prepending a header.
//
// Users which need more complex structure of query results, should
// transform it to such using appropriate visitors.
// TODO: insert reference to such visitors here.
//
// Query results have dynamic format. In some queries (maybe even in typical
// ones), we don't need to send partition or clustering keys back to the
// client, because they are already specified in the query request, and not
// queried for. The query results hold keys optionally.
//
// Also, meta-data like cell timestamp and expiry is optional. It is only needed
// if the query has writetime() or ttl() functions in it, which it typically
// won't have.
//
// Related headers:
//  - query-result-reader.hh
//  - query-result-writer.hh

//
// Query results are serialized to the following form:
//
// <result>          ::= <partition>*
// <partition>       ::= <row-count> [ <partition-key> ] [ <static-row> ] <row>*
// <static-row>      ::= <row>
// <row>             ::= <row-length> <cell>+
// <cell>            ::= <atomic-cell> | <collection-cell>
// <atomic-cell>     ::= <present-byte> [ <timestamp> <expiry> ] <value>
// <collection-cell> ::= <blob>
//
// <value>           ::= <blob>
// <blob>            ::= <blob-length> <uint8_t>*
// <timestamp>       ::= <uint64_t>
// <expiry>          ::= <int32_t>
// <present-byte>    ::= <int8_t>
// <row-length>      ::= <uint32_t>
// <row-count>       ::= <uint32_t>
// <blob-length>     ::= <uint32_t>
//
class result {
    bytes_ostream _w;
public:
    class builder;
    class partition_writer;
    class row_writer;
    friend class result_merger;

    result() {}
    result(bytes_ostream&& w) : _w(std::move(w)) {}
    result(result&&) = default;
    result(const result&) = default;
    result& operator=(result&&) = default;
    result& operator=(const result&) = default;

    const bytes_ostream& buf() const {
        return _w;
    }

    result_digest digest() {
        CryptoPP::Weak::MD5 hash;
        bytes b(bytes::initialized_later(), CryptoPP::Weak::MD5::DIGESTSIZE);
        bytes_view v = _w.linearize();
        hash.CalculateDigest(reinterpret_cast<unsigned char*>(b.begin()), reinterpret_cast<const unsigned char*>(v.begin()), v.size());
        return result_digest(std::move(b));
    }
    sstring pretty_print(schema_ptr, const query::partition_slice&) const;
};

}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2017 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include "schema_fwd.hh"
#include "query-request.hh"
#include "mutation_fragment.hh"
#include "partition_version.hh"
#include "tracing/tracing.hh"
#include "row_cache.hh"

namespace cache {

/*
* Represent a flat reader to the underlying source.
* This reader automatically makes sure that it's up to date with all cache updates
*/
class autoupdating_underlying_reader final {
    row_cache& _cache;
    read_context& _read_context;
    flat_mutation_reader_opt _reader;
    utils::phased_barrier::phase_type _reader_creation_phase = 0;
    dht::partition_range _range = { };
    std::optional<dht::decorated_key> _last_key;
    std::optional<dht::decorated_key> _new_last_key;

    future<> close_reader() noexcept {
        return _reader ? _reader->close() : make_ready_future<>();
    }
public:
    autoupdating_underlying_reader(row_cache& cache, read_context& context)
        : _cache(cache)
        , _read_context(context)
    { }
    future<mutation_fragment_opt> move_to_next_partition(db::timeout_clock::time_point timeout) {
        _last_key = std::move(_new_last_key);
        auto start = population_range_start();
        auto phase = _cache.phase_of(start);
        auto refresh_reader = make_ready_future<>();
        if (!_reader || _reader_creation_phase != phase) {
            if (_last_key) {
                auto cmp = dht::ring_position_comparator(*_cache._schema);
                auto&& new_range = _range.split_after(*_last_key, cmp);
                if (!new_range) {
                  return close_reader().then([] {
                    return make_ready_future<mutation_fragment_opt>();
                  });
                }
                _range = std::move(*new_range);
                _last_key = {};
            }
            if (_reader) {
                ++_cache._tracker._stats.underlying_recreations;
            }
          refresh_reader = close_reader().then([this, phase] {
            _reader = _cache.create_underlying_reader(_read_context, _cache.snapshot_for_phase(phase), _range);
            _reader_creation_phase = phase;
          });
        }
     return refresh_reader.then([this, timeout] {
      return _reader->next_partition().then([this, timeout] {
        if (_reader->is_end_of_stream() && _reader->is_buffer_empty()) {
            return make_ready_future<mutation_fragment_opt>();
        }
        return (*_reader)(timeout).then([this] (auto&& mfopt) {
            if (mfopt) {
                assert(mfopt->is_partition_start());
                _new_last_key = mfopt->as_partition_start().key();
            }
            return std::move(mfopt);
        });
      });
     });
    }
    future<> fast_forward_to(dht::partition_range&& range, db::timeout_clock::time_point timeout) {
        auto snapshot_and_phase = _cache.snapshot_of(dht::ring_position_view::for_range_start(_range));
        return fast_forward_to(std::move(range), snapshot_and_phase.snapshot, snapshot_and_phase.phase, timeout);
    }
    future<> fast_forward_to(dht::partition_range&& range, mutation_source& snapshot, row_cache::phase_type phase, db::timeout_clock::time_point timeout) {
        _range = std::move(range);
        _last_key = { };
        _new_last_key = { };
        if (_reader) {
            if (_reader_creation_phase == phase) {
                ++_cache._tracker._stats.underlying_partition_skips;
                return _reader->fast_forward_to(_range, timeout);
            } else {
                ++_cache._tracker._stats.underlying_recreations;
            }
        }
      return close_reader().then([this, &snapshot, phase] {
        _reader = _cache.create_underlying_reader(_read_context, snapshot, _range);
        _reader_creation_phase = phase;
      });
    }
    utils::phased_barrier::phase_type creation_phase() const {
        return _reader_creation_phase;
    }
    const dht::partition_range& range() const {
        return _range;
    }
    flat_mutation_reader& underlying() { return *_reader; }
    dht::ring_position_view population_range_start() const {
        return _last_key ? dht::ring_position_view::for_after_key(*_last_key)
                         : dht::ring_position_view::for_range_start(_range);
    }
};

class read_context final : public enable_lw_shared_from_this<read_context> {
    row_cache& _cache;
    schema_ptr _schema;
    reader_permit _permit;
    const dht::partition_range& _range;
    const query::partition_slice& _slice;
    const io_priority_class& _pc;
    tracing::trace_state_ptr _trace_state;
    mutation_reader::forwarding _fwd_mr;
    bool _range_query;
    // When reader enters a partition, it must be set up for reading that
    // partition from the underlying mutation source (_underlying) in one of two ways:
    //
    //  1) either _underlying is already in that partition
    //
    //  2) _underlying is before the partition, then _underlying_snapshot and _key
    //     are set so that _underlying_flat can be fast forwarded to the right partition.
    //
    autoupdating_underlying_reader _underlying;
    uint64_t _underlying_created = 0;

    mutation_source_opt _underlying_snapshot;
    dht::partition_range _sm_range;
    std::optional<dht::decorated_key> _key;
    bool _partition_exists;
    row_cache::phase_type _phase;
public:
    read_context(row_cache& cache,
            schema_ptr schema,
            reader_permit permit,
            const dht::partition_range& range,
            const query::partition_slice& slice,
            const io_priority_class& pc,
            tracing::trace_state_ptr trace_state,
            mutation_reader::forwarding fwd_mr)
        : _cache(cache)
        , _schema(std::move(schema))
        , _permit(std::move(permit))
        , _range(range)
        , _slice(slice)
        , _pc(pc)
        , _trace_state(std::move(trace_state))
        , _fwd_mr(fwd_mr)
        , _range_query(!query::is_single_partition(range))
        , _underlying(_cache, *this)
    {
        ++_cache._tracker._stats.reads;
        if (!_range_query) {
            _key = range.start()->value().as_decorated_key();
        }
    }
    ~read_context() {
        ++_cache._tracker._stats.reads_done;
        if (_underlying_created) {
            _cache._stats.reads_with_misses.mark();
            ++_cache._tracker._stats.reads_with_misses;
        } else {
            _cache._stats.reads_with_no_misses.mark();
        }
    }
    read_context(const read_context&) = delete;
    row_cache& cache() { return _cache; }
    const schema_ptr& schema() const { return _schema; }
    reader_permit permit() const { return _permit; }
    const dht::partition_range& range() const { return _range; }
    const query::partition_slice& slice() const { return _slice; }
    const io_priority_class& pc() const { return _pc; }
    tracing::trace_state_ptr trace_state() const { return _trace_state; }
    mutation_reader::forwarding fwd_mr() const { return _fwd_mr; }
    bool is_range_query() const { return _range_query; }
    autoupdating_underlying_reader& underlying() { return _underlying; }
    row_cache::phase_type phase() const { return _phase; }
    const dht::decorated_key& key() const { return *_key; }
    bool partition_exists() const { return _partition_exists; }
    void on_underlying_created() { ++_underlying_created; }
    bool digest_requested() const { return _slice.options.contains<query::partition_slice::option::with_digest>(); }
public:
    future<> ensure_underlying(db::timeout_clock::time_point timeout) {
        if (_underlying_snapshot) {
            return create_underlying(timeout).then([this, timeout] {
                return _underlying.underlying()(timeout).then([this] (mutation_fragment_opt&& mfopt) {
                    _partition_exists = bool(mfopt);
                });
            });
        }
        // We know that partition exists because all the callers of
        // enter_partition(const dht::decorated_key&, row_cache::phase_type)
        // check that and there's no other way of setting _underlying_snapshot
        // to empty. Except for calling create_underlying.
        _partition_exists = true;
        return make_ready_future<>();
    }
public:
    future<> create_underlying(db::timeout_clock::time_point timeout);
    void enter_partition(const dht::decorated_key& dk, mutation_source& snapshot, row_cache::phase_type phase) {
        _phase = phase;
        _underlying_snapshot = snapshot;
        _key = dk;
    }
    // Precondition: each caller needs to make sure that partition with |dk| key
    //               exists in underlying before calling this function.
    void enter_partition(const dht::decorated_key& dk, row_cache::phase_type phase) {
        _phase = phase;
        _underlying_snapshot = {};
        _key = dk;
    }
};

}
<commit_msg>row_cache: autoupdating_underlying_reader: add close method<commit_after>/*
 * Copyright (C) 2017 ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include "schema_fwd.hh"
#include "query-request.hh"
#include "mutation_fragment.hh"
#include "partition_version.hh"
#include "tracing/tracing.hh"
#include "row_cache.hh"

namespace cache {

/*
* Represent a flat reader to the underlying source.
* This reader automatically makes sure that it's up to date with all cache updates
*/
class autoupdating_underlying_reader final {
    row_cache& _cache;
    read_context& _read_context;
    flat_mutation_reader_opt _reader;
    utils::phased_barrier::phase_type _reader_creation_phase = 0;
    dht::partition_range _range = { };
    std::optional<dht::decorated_key> _last_key;
    std::optional<dht::decorated_key> _new_last_key;

    future<> close_reader() noexcept {
        return _reader ? _reader->close() : make_ready_future<>();
    }
public:
    autoupdating_underlying_reader(row_cache& cache, read_context& context)
        : _cache(cache)
        , _read_context(context)
    { }
    future<mutation_fragment_opt> move_to_next_partition(db::timeout_clock::time_point timeout) {
        _last_key = std::move(_new_last_key);
        auto start = population_range_start();
        auto phase = _cache.phase_of(start);
        auto refresh_reader = make_ready_future<>();
        if (!_reader || _reader_creation_phase != phase) {
            if (_last_key) {
                auto cmp = dht::ring_position_comparator(*_cache._schema);
                auto&& new_range = _range.split_after(*_last_key, cmp);
                if (!new_range) {
                  return close_reader().then([] {
                    return make_ready_future<mutation_fragment_opt>();
                  });
                }
                _range = std::move(*new_range);
                _last_key = {};
            }
            if (_reader) {
                ++_cache._tracker._stats.underlying_recreations;
            }
          refresh_reader = close_reader().then([this, phase] {
            _reader = _cache.create_underlying_reader(_read_context, _cache.snapshot_for_phase(phase), _range);
            _reader_creation_phase = phase;
          });
        }
     return refresh_reader.then([this, timeout] {
      return _reader->next_partition().then([this, timeout] {
        if (_reader->is_end_of_stream() && _reader->is_buffer_empty()) {
            return make_ready_future<mutation_fragment_opt>();
        }
        return (*_reader)(timeout).then([this] (auto&& mfopt) {
            if (mfopt) {
                assert(mfopt->is_partition_start());
                _new_last_key = mfopt->as_partition_start().key();
            }
            return std::move(mfopt);
        });
      });
     });
    }
    future<> fast_forward_to(dht::partition_range&& range, db::timeout_clock::time_point timeout) {
        auto snapshot_and_phase = _cache.snapshot_of(dht::ring_position_view::for_range_start(_range));
        return fast_forward_to(std::move(range), snapshot_and_phase.snapshot, snapshot_and_phase.phase, timeout);
    }
    future<> fast_forward_to(dht::partition_range&& range, mutation_source& snapshot, row_cache::phase_type phase, db::timeout_clock::time_point timeout) {
        _range = std::move(range);
        _last_key = { };
        _new_last_key = { };
        if (_reader) {
            if (_reader_creation_phase == phase) {
                ++_cache._tracker._stats.underlying_partition_skips;
                return _reader->fast_forward_to(_range, timeout);
            } else {
                ++_cache._tracker._stats.underlying_recreations;
            }
        }
      return close_reader().then([this, &snapshot, phase] {
        _reader = _cache.create_underlying_reader(_read_context, snapshot, _range);
        _reader_creation_phase = phase;
      });
    }
    future<> close() noexcept {
        return close_reader();
    }
    utils::phased_barrier::phase_type creation_phase() const {
        return _reader_creation_phase;
    }
    const dht::partition_range& range() const {
        return _range;
    }
    flat_mutation_reader& underlying() { return *_reader; }
    dht::ring_position_view population_range_start() const {
        return _last_key ? dht::ring_position_view::for_after_key(*_last_key)
                         : dht::ring_position_view::for_range_start(_range);
    }
};

class read_context final : public enable_lw_shared_from_this<read_context> {
    row_cache& _cache;
    schema_ptr _schema;
    reader_permit _permit;
    const dht::partition_range& _range;
    const query::partition_slice& _slice;
    const io_priority_class& _pc;
    tracing::trace_state_ptr _trace_state;
    mutation_reader::forwarding _fwd_mr;
    bool _range_query;
    // When reader enters a partition, it must be set up for reading that
    // partition from the underlying mutation source (_underlying) in one of two ways:
    //
    //  1) either _underlying is already in that partition
    //
    //  2) _underlying is before the partition, then _underlying_snapshot and _key
    //     are set so that _underlying_flat can be fast forwarded to the right partition.
    //
    autoupdating_underlying_reader _underlying;
    uint64_t _underlying_created = 0;

    mutation_source_opt _underlying_snapshot;
    dht::partition_range _sm_range;
    std::optional<dht::decorated_key> _key;
    bool _partition_exists;
    row_cache::phase_type _phase;
public:
    read_context(row_cache& cache,
            schema_ptr schema,
            reader_permit permit,
            const dht::partition_range& range,
            const query::partition_slice& slice,
            const io_priority_class& pc,
            tracing::trace_state_ptr trace_state,
            mutation_reader::forwarding fwd_mr)
        : _cache(cache)
        , _schema(std::move(schema))
        , _permit(std::move(permit))
        , _range(range)
        , _slice(slice)
        , _pc(pc)
        , _trace_state(std::move(trace_state))
        , _fwd_mr(fwd_mr)
        , _range_query(!query::is_single_partition(range))
        , _underlying(_cache, *this)
    {
        ++_cache._tracker._stats.reads;
        if (!_range_query) {
            _key = range.start()->value().as_decorated_key();
        }
    }
    ~read_context() {
        ++_cache._tracker._stats.reads_done;
        if (_underlying_created) {
            _cache._stats.reads_with_misses.mark();
            ++_cache._tracker._stats.reads_with_misses;
        } else {
            _cache._stats.reads_with_no_misses.mark();
        }
    }
    read_context(const read_context&) = delete;
    row_cache& cache() { return _cache; }
    const schema_ptr& schema() const { return _schema; }
    reader_permit permit() const { return _permit; }
    const dht::partition_range& range() const { return _range; }
    const query::partition_slice& slice() const { return _slice; }
    const io_priority_class& pc() const { return _pc; }
    tracing::trace_state_ptr trace_state() const { return _trace_state; }
    mutation_reader::forwarding fwd_mr() const { return _fwd_mr; }
    bool is_range_query() const { return _range_query; }
    autoupdating_underlying_reader& underlying() { return _underlying; }
    row_cache::phase_type phase() const { return _phase; }
    const dht::decorated_key& key() const { return *_key; }
    bool partition_exists() const { return _partition_exists; }
    void on_underlying_created() { ++_underlying_created; }
    bool digest_requested() const { return _slice.options.contains<query::partition_slice::option::with_digest>(); }
public:
    future<> ensure_underlying(db::timeout_clock::time_point timeout) {
        if (_underlying_snapshot) {
            return create_underlying(timeout).then([this, timeout] {
                return _underlying.underlying()(timeout).then([this] (mutation_fragment_opt&& mfopt) {
                    _partition_exists = bool(mfopt);
                });
            });
        }
        // We know that partition exists because all the callers of
        // enter_partition(const dht::decorated_key&, row_cache::phase_type)
        // check that and there's no other way of setting _underlying_snapshot
        // to empty. Except for calling create_underlying.
        _partition_exists = true;
        return make_ready_future<>();
    }
public:
    future<> create_underlying(db::timeout_clock::time_point timeout);
    void enter_partition(const dht::decorated_key& dk, mutation_source& snapshot, row_cache::phase_type phase) {
        _phase = phase;
        _underlying_snapshot = snapshot;
        _key = dk;
    }
    // Precondition: each caller needs to make sure that partition with |dk| key
    //               exists in underlying before calling this function.
    void enter_partition(const dht::decorated_key& dk, row_cache::phase_type phase) {
        _phase = phase;
        _underlying_snapshot = {};
        _key = dk;
    }
};

}
<|endoftext|>


<commit_before>#include "MainComponent.h"
#include "RenderableComponent.h"
#include "wiRenderer.h"
#include "wiHelper.h"
#include "wiTimer.h"
#include "wiCpuInfo.h"
#include "wiInputManager.h"
#include "wiBackLog.h"
#include "MainComponent_BindLua.h"
#include "WickedEngine.h"

MainComponent::MainComponent()
{
	screenW = 0;
	screenH = 0;
	fullscreen = false;

	activeComponent = new RenderableComponent();

	setFrameSkip(true);
	setTargetFrameRate(60);
	setApplicationControlLostThreshold(10);

	infoDisplay = InfoDisplayer();
	colorGradingPaletteDisplayEnabled = false;
}

MainComponent::~MainComponent()
{
	activeComponent->Unload();
}

void MainComponent::Initialize()
{
	wiLua::GetGlobal()->RegisterObject(MainComponent_BindLua::className, "main", new MainComponent_BindLua(this));
}

void MainComponent::activateComponent(RenderableComponent* component)
{
	if (component == nullptr)
	{
		return;
	}

	activeComponent->Stop();
	component->Start();

	activeComponent = component;
}

void MainComponent::run()
{
	static bool startupScriptProcessed = false;
	if (!startupScriptProcessed) {
		wiLua::GetGlobal()->RunFile("startup.lua");
		startupScriptProcessed = true;
	}

	static wiTimer timer = wiTimer();
	static double accumulator = 0.0;
	const double elapsedTime = timer.elapsed() / 1000.0;
	timer.record();

	wiLua::GetGlobal()->SetDeltaTime(elapsedTime);

	if (frameskip)
	{
		accumulator += elapsedTime;
		if (accumulator > applicationControlLostThreshold) //application probably lost control
			accumulator = 0;

		while (accumulator >= targetFrameRateInv)
		{

			Update();

			accumulator -= targetFrameRateInv;

		}

	}
	else
	{
		Update();
	}

	Render();

	wiRenderer::Present(bind(&MainComponent::Compose, this));
}

void MainComponent::Update()
{
	wiInputManager::Update();
	wiCpuInfo::Frame();
	wiBackLog::Update();

	wiLua::GetGlobal()->Update();

	getActiveComponent()->Update();
}

void MainComponent::Render()
{
	wiLua::GetGlobal()->Render();

	getActiveComponent()->Render();
}

void MainComponent::Compose()
{
	getActiveComponent()->Compose();

	// Draw the information display
	if (infoDisplay.active)
	{
		stringstream ss("");
		if (infoDisplay.watermark)
		{
			ss << string("Wicked Engine ") + string(WICKED_ENGINE_VERSION) << endl;
		}
		if (infoDisplay.fpsinfo)
		{
			ss.precision(2);
			ss << fixed << wiFrameRate::FPS() << " FPS" << endl;
		}
		if (infoDisplay.cpuinfo)
		{
			ss << "CPU: " << wiCpuInfo::GetCpuPercentage() << "%" << endl;
		}
		wiFont(ss.str(), wiFontProps(0, 0, infoDisplay.size, WIFALIGN_LEFT, WIFALIGN_TOP, infoDisplay.size)).Draw();
	}

	// Draw the color grading palette
	if (colorGradingPaletteDisplayEnabled)
	{
		wiImage::BatchBegin();
		wiImage::Draw(wiTextureHelper::getInstance()->getColorGradeDefault(), wiImageEffects(0, 0, 256, 16));
	}

	wiBackLog::Draw();
}

#ifndef WINSTORE_SUPPORT
bool MainComponent::setWindow(HWND hWnd, HINSTANCE hInst)
{
	window = hWnd;
	instance = hInst;

	if (screenH == 0 && screenW == 0)
	{
		RECT rect = RECT();
		GetClientRect(hWnd, &rect);
		screenW = rect.right - rect.left;
		screenH = rect.bottom - rect.top;
	}

	if (FAILED(wiRenderer::InitDevice(window, screenW, screenH, !fullscreen)))
	{
		wiHelper::messageBox("Could not initialize D3D device!", "Fatal Error!", window);
		return false;
	}

	return true;
}
#else
bool MainComponent::setWindow(Windows::UI::Core::CoreWindow^ window)
{
	screenW = (int)window->Bounds.Width;
	screenH = (int)window->Bounds.Height;
	if (FAILED(wiRenderer::InitDevice(window)))
	{
		wiHelper::messageBox("Could not initialize D3D device!", "Fatal Error!");
		return false;
	}

	return true;
}
#endif

<commit_msg>color grading palette display updated<commit_after>#include "MainComponent.h"
#include "RenderableComponent.h"
#include "wiRenderer.h"
#include "wiHelper.h"
#include "wiTimer.h"
#include "wiCpuInfo.h"
#include "wiInputManager.h"
#include "wiBackLog.h"
#include "MainComponent_BindLua.h"
#include "WickedEngine.h"

MainComponent::MainComponent()
{
	screenW = 0;
	screenH = 0;
	fullscreen = false;

	activeComponent = new RenderableComponent();

	setFrameSkip(true);
	setTargetFrameRate(60);
	setApplicationControlLostThreshold(10);

	infoDisplay = InfoDisplayer();
	colorGradingPaletteDisplayEnabled = false;
}

MainComponent::~MainComponent()
{
	activeComponent->Unload();
}

void MainComponent::Initialize()
{
	wiLua::GetGlobal()->RegisterObject(MainComponent_BindLua::className, "main", new MainComponent_BindLua(this));
}

void MainComponent::activateComponent(RenderableComponent* component)
{
	if (component == nullptr)
	{
		return;
	}

	activeComponent->Stop();
	component->Start();

	activeComponent = component;
}

void MainComponent::run()
{
	static bool startupScriptProcessed = false;
	if (!startupScriptProcessed) {
		wiLua::GetGlobal()->RunFile("startup.lua");
		startupScriptProcessed = true;
	}

	static wiTimer timer = wiTimer();
	static double accumulator = 0.0;
	const double elapsedTime = timer.elapsed() / 1000.0;
	timer.record();

	wiLua::GetGlobal()->SetDeltaTime(elapsedTime);

	if (frameskip)
	{
		accumulator += elapsedTime;
		if (accumulator > applicationControlLostThreshold) //application probably lost control
			accumulator = 0;

		while (accumulator >= targetFrameRateInv)
		{

			Update();

			accumulator -= targetFrameRateInv;

		}

	}
	else
	{
		Update();
	}

	Render();

	wiRenderer::Present(bind(&MainComponent::Compose, this));
}

void MainComponent::Update()
{
	wiInputManager::Update();
	wiCpuInfo::Frame();
	wiBackLog::Update();

	wiLua::GetGlobal()->Update();

	getActiveComponent()->Update();
}

void MainComponent::Render()
{
	wiLua::GetGlobal()->Render();

	getActiveComponent()->Render();
}

void MainComponent::Compose()
{
	getActiveComponent()->Compose();

	// Draw the information display
	if (infoDisplay.active)
	{
		stringstream ss("");
		if (infoDisplay.watermark)
		{
			ss << string("Wicked Engine ") + string(WICKED_ENGINE_VERSION) << endl;
		}
		if (infoDisplay.fpsinfo)
		{
			ss.precision(2);
			ss << fixed << wiFrameRate::FPS() << " FPS" << endl;
		}
		if (infoDisplay.cpuinfo)
		{
			ss << "CPU: " << wiCpuInfo::GetCpuPercentage() << "%" << endl;
		}
		wiFont(ss.str(), wiFontProps(0, 0, infoDisplay.size, WIFALIGN_LEFT, WIFALIGN_TOP, infoDisplay.size)).Draw();
	}

	// Draw the color grading palette
	if (colorGradingPaletteDisplayEnabled)
	{
		wiImage::BatchBegin();
		wiImage::Draw(wiTextureHelper::getInstance()->getColorGradeDefault(), wiImageEffects(0, 0, 256, 16));
		wiImage::Draw(wiRenderer::GetColorGrading(), wiImageEffects(screenW-256, 0, 256, 16));
	}

	wiBackLog::Draw();
}

#ifndef WINSTORE_SUPPORT
bool MainComponent::setWindow(HWND hWnd, HINSTANCE hInst)
{
	window = hWnd;
	instance = hInst;

	if (screenH == 0 && screenW == 0)
	{
		RECT rect = RECT();
		GetClientRect(hWnd, &rect);
		screenW = rect.right - rect.left;
		screenH = rect.bottom - rect.top;
	}

	if (FAILED(wiRenderer::InitDevice(window, screenW, screenH, !fullscreen)))
	{
		wiHelper::messageBox("Could not initialize D3D device!", "Fatal Error!", window);
		return false;
	}

	return true;
}
#else
bool MainComponent::setWindow(Windows::UI::Core::CoreWindow^ window)
{
	screenW = (int)window->Bounds.Width;
	screenH = (int)window->Bounds.Height;
	if (FAILED(wiRenderer::InitDevice(window)))
	{
		wiHelper::messageBox("Could not initialize D3D device!", "Fatal Error!");
		return false;
	}

	return true;
}
#endif

<|endoftext|>