1 | // Copyright 2016 The SwiftShader Authors. All Rights Reserved. |
2 | // |
3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | // you may not use this file except in compliance with the License. |
5 | // You may obtain a copy of the License at |
6 | // |
7 | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | // |
9 | // Unless required by applicable law or agreed to in writing, software |
10 | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | // See the License for the specific language governing permissions and |
13 | // limitations under the License. |
14 | |
15 | #ifndef sw_Blitter_hpp |
16 | #define sw_Blitter_hpp |
17 | |
18 | #include "Memset.hpp" |
19 | #include "RoutineCache.hpp" |
20 | #include "Reactor/Reactor.hpp" |
21 | #include "Vulkan/VkFormat.h" |
22 | |
23 | #include <mutex> |
24 | #include <cstring> |
25 | |
26 | namespace vk |
27 | { |
28 | class Image; |
29 | class Buffer; |
30 | } |
31 | |
32 | namespace sw |
33 | { |
34 | class Blitter |
35 | { |
36 | struct Options |
37 | { |
38 | explicit Options() = default; |
39 | explicit Options(bool filter, bool allowSRGBConversion) |
40 | : writeMask(0xF), clearOperation(false), filter(filter), allowSRGBConversion(allowSRGBConversion), clampToEdge(false) {} |
41 | explicit Options(unsigned int writeMask) |
42 | : writeMask(writeMask), clearOperation(true), filter(false), allowSRGBConversion(true), clampToEdge(false) {} |
43 | |
44 | union |
45 | { |
46 | struct |
47 | { |
48 | bool writeRed : 1; |
49 | bool writeGreen : 1; |
50 | bool writeBlue : 1; |
51 | bool writeAlpha : 1; |
52 | }; |
53 | |
54 | unsigned char writeMask; |
55 | }; |
56 | |
57 | bool clearOperation : 1; |
58 | bool filter : 1; |
59 | bool allowSRGBConversion : 1; |
60 | bool clampToEdge : 1; |
61 | }; |
62 | |
63 | struct State : Memset<State>, Options |
64 | { |
65 | State() : Memset(this, 0) {} |
66 | State(const Options &options) : Memset(this, 0), Options(options) {} |
67 | State(vk::Format sourceFormat, vk::Format destFormat, int srcSamples, int destSamples, const Options &options) : |
68 | Memset(this, 0), Options(options), sourceFormat(sourceFormat), destFormat(destFormat), srcSamples(srcSamples), destSamples(destSamples) {} |
69 | |
70 | bool operator==(const State &state) const |
71 | { |
72 | static_assert(is_memcmparable<State>::value, "Cannot memcmp State" ); |
73 | return memcmp(this, &state, sizeof(State)) == 0; |
74 | } |
75 | |
76 | vk::Format sourceFormat; |
77 | vk::Format destFormat; |
78 | int srcSamples = 0; |
79 | int destSamples = 0; |
80 | }; |
81 | |
82 | struct BlitData |
83 | { |
84 | void *source; |
85 | void *dest; |
86 | int sPitchB; |
87 | int dPitchB; |
88 | int sSliceB; |
89 | int dSliceB; |
90 | |
91 | float x0; |
92 | float y0; |
93 | float w; |
94 | float h; |
95 | |
96 | int y0d; |
97 | int y1d; |
98 | int x0d; |
99 | int x1d; |
100 | |
101 | int sWidth; |
102 | int sHeight; |
103 | }; |
104 | |
105 | struct CubeBorderData |
106 | { |
107 | void *layers; |
108 | int pitchB; |
109 | uint32_t layerSize; |
110 | uint32_t dim; |
111 | }; |
112 | |
113 | public: |
114 | Blitter(); |
115 | virtual ~Blitter(); |
116 | |
117 | void clear(void *pixel, vk::Format format, vk::Image *dest, const vk::Format& viewFormat, const VkImageSubresourceRange& subresourceRange, const VkRect2D* renderArea = nullptr); |
118 | |
119 | void blit(const vk::Image *src, vk::Image *dst, VkImageBlit region, VkFilter filter); |
120 | void blitToBuffer(const vk::Image *src, VkImageSubresourceLayers subresource, VkOffset3D offset, VkExtent3D extent, uint8_t *dst, int bufferRowPitch, int bufferSlicePitch); |
121 | void blitFromBuffer(const vk::Image *dst, VkImageSubresourceLayers subresource, VkOffset3D offset, VkExtent3D extent, uint8_t *src, int bufferRowPitch, int bufferSlicePitch); |
122 | |
123 | void updateBorders(vk::Image* image, const VkImageSubresourceLayers& subresourceLayers); |
124 | |
125 | private: |
126 | enum Edge { TOP, BOTTOM, RIGHT, LEFT }; |
127 | |
128 | bool fastClear(void *pixel, vk::Format format, vk::Image *dest, const vk::Format& viewFormat, const VkImageSubresourceRange& subresourceRange, const VkRect2D* renderArea); |
129 | |
130 | Float4 readFloat4(Pointer<Byte> element, const State &state); |
131 | void write(Float4 &color, Pointer<Byte> element, const State &state); |
132 | Int4 readInt4(Pointer<Byte> element, const State &state); |
133 | void write(Int4 &color, Pointer<Byte> element, const State &state); |
134 | static void ApplyScaleAndClamp(Float4 &value, const State &state, bool preScaled = false); |
135 | static Int ComputeOffset(Int &x, Int &y, Int &pitchB, int bytes, bool quadLayout); |
136 | static Float4 LinearToSRGB(Float4 &color); |
137 | static Float4 sRGBtoLinear(Float4 &color); |
138 | |
139 | using BlitFunction = FunctionT<void(const BlitData*)>; |
140 | using BlitRoutineType = BlitFunction::RoutineType; |
141 | BlitRoutineType getBlitRoutine(const State &state); |
142 | BlitRoutineType generate(const State &state); |
143 | |
144 | using CornerUpdateFunction = FunctionT<void(const CubeBorderData*)>; |
145 | using CornerUpdateRoutineType = CornerUpdateFunction::RoutineType; |
146 | CornerUpdateRoutineType getCornerUpdateRoutine(const State &state); |
147 | CornerUpdateRoutineType generateCornerUpdate(const State& state); |
148 | void computeCubeCorner(Pointer<Byte>& layer, Int& x0, Int& x1, Int& y0, Int& y1, Int& pitchB, const State& state); |
149 | |
150 | void copyCubeEdge(vk::Image* image, |
151 | const VkImageSubresourceLayers& dstSubresourceLayers, Edge dstEdge, |
152 | const VkImageSubresourceLayers& srcSubresourceLayers, Edge srcEdge); |
153 | |
154 | std::mutex blitMutex; |
155 | RoutineCacheT<State, BlitFunction::CFunctionType> blitCache; // guarded by blitMutex |
156 | std::mutex cornerUpdateMutex; |
157 | RoutineCacheT<State, CornerUpdateFunction::CFunctionType> cornerUpdateCache; // guarded by cornerUpdateMutex |
158 | }; |
159 | } |
160 | |
161 | #endif // sw_Blitter_hpp |
162 | |