|  | // Copyright 2016 The SwiftShader Authors. All Rights Reserved. | 
|  | // | 
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | // you may not use this file except in compliance with the License. | 
|  | // You may obtain a copy of the License at | 
|  | // | 
|  | //    http://www.apache.org/licenses/LICENSE-2.0 | 
|  | // | 
|  | // Unless required by applicable law or agreed to in writing, software | 
|  | // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | // See the License for the specific language governing permissions and | 
|  | // limitations under the License. | 
|  |  | 
|  | #ifndef sw_Blitter_hpp | 
|  | #define sw_Blitter_hpp | 
|  |  | 
|  | #include "Memset.hpp" | 
|  | #include "RoutineCache.hpp" | 
|  | #include "Reactor/Reactor.hpp" | 
|  | #include "Vulkan/VkFormat.hpp" | 
|  |  | 
|  | #include "marl/mutex.h" | 
|  | #include "marl/tsa.h" | 
|  |  | 
|  | #include <cstring> | 
|  |  | 
|  | namespace vk { | 
|  |  | 
|  | class Image; | 
|  | class Buffer; | 
|  |  | 
|  | }  // namespace vk | 
|  |  | 
|  | namespace sw { | 
|  |  | 
|  | class Blitter | 
|  | { | 
|  | struct Options | 
|  | { | 
|  | explicit Options() = default; | 
|  | explicit Options(bool filter, bool allowSRGBConversion) | 
|  | : writeMask(0xF) | 
|  | , clearOperation(false) | 
|  | , filter(filter) | 
|  | , allowSRGBConversion(allowSRGBConversion) | 
|  | , clampToEdge(false) | 
|  | {} | 
|  | explicit Options(unsigned int writeMask) | 
|  | : writeMask(writeMask) | 
|  | , clearOperation(true) | 
|  | , filter(false) | 
|  | , allowSRGBConversion(true) | 
|  | , clampToEdge(false) | 
|  | {} | 
|  |  | 
|  | union | 
|  | { | 
|  | struct | 
|  | { | 
|  | bool writeRed : 1; | 
|  | bool writeGreen : 1; | 
|  | bool writeBlue : 1; | 
|  | bool writeAlpha : 1; | 
|  | }; | 
|  |  | 
|  | unsigned char writeMask; | 
|  | }; | 
|  |  | 
|  | bool clearOperation : 1; | 
|  | bool filter : 1; | 
|  | bool allowSRGBConversion : 1; | 
|  | bool clampToEdge : 1; | 
|  | }; | 
|  |  | 
|  | struct State : Memset<State>, Options | 
|  | { | 
|  | State() | 
|  | : Memset(this, 0) | 
|  | {} | 
|  | State(const Options &options) | 
|  | : Memset(this, 0) | 
|  | , Options(options) | 
|  | {} | 
|  | State(vk::Format sourceFormat, vk::Format destFormat, int srcSamples, int destSamples, const Options &options) | 
|  | : Memset(this, 0) | 
|  | , Options(options) | 
|  | , sourceFormat(sourceFormat) | 
|  | , destFormat(destFormat) | 
|  | , srcSamples(srcSamples) | 
|  | , destSamples(destSamples) | 
|  | {} | 
|  |  | 
|  | vk::Format sourceFormat; | 
|  | vk::Format destFormat; | 
|  | int srcSamples = 0; | 
|  | int destSamples = 0; | 
|  | bool filter3D = false; | 
|  | }; | 
|  | friend std::hash<Blitter::State>; | 
|  |  | 
|  | struct BlitData | 
|  | { | 
|  | void *source; | 
|  | void *dest; | 
|  | int sPitchB; | 
|  | int dPitchB; | 
|  | int sSliceB; | 
|  | int dSliceB; | 
|  |  | 
|  | float x0; | 
|  | float y0; | 
|  | float z0; | 
|  | float w; | 
|  | float h; | 
|  | float d; | 
|  |  | 
|  | int x0d; | 
|  | int x1d; | 
|  | int y0d; | 
|  | int y1d; | 
|  | int z0d; | 
|  | int z1d; | 
|  |  | 
|  | int sWidth; | 
|  | int sHeight; | 
|  | int sDepth; | 
|  |  | 
|  | bool filter3D; | 
|  | }; | 
|  |  | 
|  | struct CubeBorderData | 
|  | { | 
|  | void *layers; | 
|  | int pitchB; | 
|  | uint32_t layerSize; | 
|  | uint32_t dim; | 
|  | }; | 
|  |  | 
|  | public: | 
|  | Blitter(); | 
|  | virtual ~Blitter(); | 
|  |  | 
|  | void clear(void *clearValue, vk::Format clearFormat, vk::Image *dest, const vk::Format &viewFormat, const VkImageSubresourceRange &subresourceRange, const VkRect2D *renderArea = nullptr); | 
|  |  | 
|  | void blit(const vk::Image *src, vk::Image *dst, VkImageBlit region, VkFilter filter); | 
|  | void copy(const vk::Image *src, uint8_t *dst, unsigned int dstPitch); | 
|  |  | 
|  | void updateBorders(vk::Image *image, const VkImageSubresource &subresource); | 
|  |  | 
|  | private: | 
|  | enum Edge | 
|  | { | 
|  | TOP, | 
|  | BOTTOM, | 
|  | RIGHT, | 
|  | LEFT | 
|  | }; | 
|  |  | 
|  | bool fastClear(void *clearValue, vk::Format clearFormat, vk::Image *dest, const vk::Format &viewFormat, const VkImageSubresourceRange &subresourceRange, const VkRect2D *renderArea); | 
|  |  | 
|  | Float4 readFloat4(Pointer<Byte> element, const State &state); | 
|  | void write(Float4 &color, Pointer<Byte> element, const State &state); | 
|  | Int4 readInt4(Pointer<Byte> element, const State &state); | 
|  | void write(Int4 &color, Pointer<Byte> element, const State &state); | 
|  | static void ApplyScaleAndClamp(Float4 &value, const State &state, bool preScaled = false); | 
|  | static Int ComputeOffset(Int &x, Int &y, Int &pitchB, int bytes); | 
|  | static Int ComputeOffset(Int &x, Int &y, Int &z, Int &sliceB, Int &pitchB, int bytes); | 
|  | static Float4 LinearToSRGB(const Float4 &color); | 
|  | static Float4 sRGBtoLinear(const Float4 &color); | 
|  |  | 
|  | using BlitFunction = FunctionT<void(const BlitData *)>; | 
|  | using BlitRoutineType = BlitFunction::RoutineType; | 
|  | BlitRoutineType getBlitRoutine(const State &state); | 
|  | BlitRoutineType generate(const State &state); | 
|  | Float4 sample(Pointer<Byte> &source, Float &x, Float &y, Float &z, | 
|  | Int &sWidth, Int &sHeight, Int &sDepth, | 
|  | Int &sSliceB, Int &sPitchB, const State &state); | 
|  |  | 
|  | using CornerUpdateFunction = FunctionT<void(const CubeBorderData *)>; | 
|  | using CornerUpdateRoutineType = CornerUpdateFunction::RoutineType; | 
|  | CornerUpdateRoutineType getCornerUpdateRoutine(const State &state); | 
|  | CornerUpdateRoutineType generateCornerUpdate(const State &state); | 
|  | void computeCubeCorner(Pointer<Byte> &layer, Int &x0, Int &x1, Int &y0, Int &y1, Int &pitchB, const State &state); | 
|  |  | 
|  | void copyCubeEdge(vk::Image *image, | 
|  | const VkImageSubresource &dstSubresource, Edge dstEdge, | 
|  | const VkImageSubresource &srcSubresource, Edge srcEdge); | 
|  |  | 
|  | marl::mutex blitMutex; | 
|  | RoutineCache<State, BlitFunction::CFunctionType> blitCache GUARDED_BY(blitMutex); | 
|  |  | 
|  | marl::mutex cornerUpdateMutex; | 
|  | RoutineCache<State, CornerUpdateFunction::CFunctionType> cornerUpdateCache GUARDED_BY(cornerUpdateMutex); | 
|  | }; | 
|  |  | 
|  | }  // namespace sw | 
|  |  | 
|  | namespace std { | 
|  |  | 
|  | template<> | 
|  | struct hash<sw::Blitter::State> | 
|  | { | 
|  | uint64_t operator()(const sw::Blitter::State &state) const | 
|  | { | 
|  | uint64_t hash = state.sourceFormat; | 
|  | hash = hash * 31 + state.destFormat; | 
|  | hash = hash * 31 + state.srcSamples; | 
|  | hash = hash * 31 + state.destSamples; | 
|  | hash = hash * 31 + state.filter3D; | 
|  | return hash; | 
|  | } | 
|  | }; | 
|  |  | 
|  | }  // namespace std | 
|  |  | 
|  | #endif  // sw_Blitter_hpp |