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
26namespace vk
27{
28 class Image;
29 class Buffer;
30}
31
32namespace 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