1cb93a386Sopenharmony_ci// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2cb93a386Sopenharmony_ci//
3cb93a386Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License");
4cb93a386Sopenharmony_ci// you may not use this file except in compliance with the License.
5cb93a386Sopenharmony_ci// You may obtain a copy of the License at
6cb93a386Sopenharmony_ci//
7cb93a386Sopenharmony_ci//    http://www.apache.org/licenses/LICENSE-2.0
8cb93a386Sopenharmony_ci//
9cb93a386Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software
10cb93a386Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS,
11cb93a386Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12cb93a386Sopenharmony_ci// See the License for the specific language governing permissions and
13cb93a386Sopenharmony_ci// limitations under the License.
14cb93a386Sopenharmony_ci
15cb93a386Sopenharmony_ci#ifndef sw_Blitter_hpp
16cb93a386Sopenharmony_ci#define sw_Blitter_hpp
17cb93a386Sopenharmony_ci
18cb93a386Sopenharmony_ci#include "Memset.hpp"
19cb93a386Sopenharmony_ci#include "RoutineCache.hpp"
20cb93a386Sopenharmony_ci#include "Reactor/Reactor.hpp"
21cb93a386Sopenharmony_ci#include "Vulkan/VkFormat.hpp"
22cb93a386Sopenharmony_ci
23cb93a386Sopenharmony_ci#include "marl/mutex.h"
24cb93a386Sopenharmony_ci#include "marl/tsa.h"
25cb93a386Sopenharmony_ci
26cb93a386Sopenharmony_ci#include <cstring>
27cb93a386Sopenharmony_ci
28cb93a386Sopenharmony_cinamespace vk {
29cb93a386Sopenharmony_ci
30cb93a386Sopenharmony_ciclass Image;
31cb93a386Sopenharmony_ciclass ImageView;
32cb93a386Sopenharmony_ciclass Buffer;
33cb93a386Sopenharmony_ci
34cb93a386Sopenharmony_ci}  // namespace vk
35cb93a386Sopenharmony_ci
36cb93a386Sopenharmony_cinamespace sw {
37cb93a386Sopenharmony_ci
38cb93a386Sopenharmony_ciclass Blitter
39cb93a386Sopenharmony_ci{
40cb93a386Sopenharmony_ci	struct Options
41cb93a386Sopenharmony_ci	{
42cb93a386Sopenharmony_ci		explicit Options() = default;
43cb93a386Sopenharmony_ci		explicit Options(bool filter, bool allowSRGBConversion)
44cb93a386Sopenharmony_ci		    : writeMask(0xF)
45cb93a386Sopenharmony_ci		    , clearOperation(false)
46cb93a386Sopenharmony_ci		    , filter(filter)
47cb93a386Sopenharmony_ci		    , allowSRGBConversion(allowSRGBConversion)
48cb93a386Sopenharmony_ci		    , clampToEdge(false)
49cb93a386Sopenharmony_ci		{}
50cb93a386Sopenharmony_ci		explicit Options(unsigned int writeMask)
51cb93a386Sopenharmony_ci		    : writeMask(writeMask)
52cb93a386Sopenharmony_ci		    , clearOperation(true)
53cb93a386Sopenharmony_ci		    , filter(false)
54cb93a386Sopenharmony_ci		    , allowSRGBConversion(true)
55cb93a386Sopenharmony_ci		    , clampToEdge(false)
56cb93a386Sopenharmony_ci		{}
57cb93a386Sopenharmony_ci
58cb93a386Sopenharmony_ci		union
59cb93a386Sopenharmony_ci		{
60cb93a386Sopenharmony_ci			struct
61cb93a386Sopenharmony_ci			{
62cb93a386Sopenharmony_ci				bool writeRed : 1;
63cb93a386Sopenharmony_ci				bool writeGreen : 1;
64cb93a386Sopenharmony_ci				bool writeBlue : 1;
65cb93a386Sopenharmony_ci				bool writeAlpha : 1;
66cb93a386Sopenharmony_ci			};
67cb93a386Sopenharmony_ci
68cb93a386Sopenharmony_ci			unsigned char writeMask;
69cb93a386Sopenharmony_ci		};
70cb93a386Sopenharmony_ci
71cb93a386Sopenharmony_ci		bool clearOperation : 1;
72cb93a386Sopenharmony_ci		bool filter : 1;
73cb93a386Sopenharmony_ci		bool allowSRGBConversion : 1;
74cb93a386Sopenharmony_ci		bool clampToEdge : 1;
75cb93a386Sopenharmony_ci	};
76cb93a386Sopenharmony_ci
77cb93a386Sopenharmony_ci	struct State : Memset<State>, Options
78cb93a386Sopenharmony_ci	{
79cb93a386Sopenharmony_ci		State()
80cb93a386Sopenharmony_ci		    : Memset(this, 0)
81cb93a386Sopenharmony_ci		{}
82cb93a386Sopenharmony_ci		State(const Options &options)
83cb93a386Sopenharmony_ci		    : Memset(this, 0)
84cb93a386Sopenharmony_ci		    , Options(options)
85cb93a386Sopenharmony_ci		{}
86cb93a386Sopenharmony_ci		State(vk::Format sourceFormat, vk::Format destFormat, int srcSamples, int destSamples, const Options &options)
87cb93a386Sopenharmony_ci		    : Memset(this, 0)
88cb93a386Sopenharmony_ci		    , Options(options)
89cb93a386Sopenharmony_ci		    , sourceFormat(sourceFormat)
90cb93a386Sopenharmony_ci		    , destFormat(destFormat)
91cb93a386Sopenharmony_ci		    , srcSamples(srcSamples)
92cb93a386Sopenharmony_ci		    , destSamples(destSamples)
93cb93a386Sopenharmony_ci		{}
94cb93a386Sopenharmony_ci
95cb93a386Sopenharmony_ci		vk::Format sourceFormat;
96cb93a386Sopenharmony_ci		vk::Format destFormat;
97cb93a386Sopenharmony_ci		int srcSamples = 0;
98cb93a386Sopenharmony_ci		int destSamples = 0;
99cb93a386Sopenharmony_ci		bool filter3D = false;
100cb93a386Sopenharmony_ci	};
101cb93a386Sopenharmony_ci	friend std::hash<Blitter::State>;
102cb93a386Sopenharmony_ci
103cb93a386Sopenharmony_ci	struct BlitData
104cb93a386Sopenharmony_ci	{
105cb93a386Sopenharmony_ci		const void *source;
106cb93a386Sopenharmony_ci		void *dest;
107cb93a386Sopenharmony_ci		uint32_t sPitchB;
108cb93a386Sopenharmony_ci		uint32_t dPitchB;
109cb93a386Sopenharmony_ci		uint32_t sSliceB;
110cb93a386Sopenharmony_ci		uint32_t dSliceB;
111cb93a386Sopenharmony_ci
112cb93a386Sopenharmony_ci		float x0;
113cb93a386Sopenharmony_ci		float y0;
114cb93a386Sopenharmony_ci		float z0;
115cb93a386Sopenharmony_ci		float w;
116cb93a386Sopenharmony_ci		float h;
117cb93a386Sopenharmony_ci		float d;
118cb93a386Sopenharmony_ci
119cb93a386Sopenharmony_ci		int x0d;
120cb93a386Sopenharmony_ci		int x1d;
121cb93a386Sopenharmony_ci		int y0d;
122cb93a386Sopenharmony_ci		int y1d;
123cb93a386Sopenharmony_ci		int z0d;
124cb93a386Sopenharmony_ci		int z1d;
125cb93a386Sopenharmony_ci
126cb93a386Sopenharmony_ci		int sWidth;
127cb93a386Sopenharmony_ci		int sHeight;
128cb93a386Sopenharmony_ci		int sDepth;
129cb93a386Sopenharmony_ci
130cb93a386Sopenharmony_ci		bool filter3D;
131cb93a386Sopenharmony_ci	};
132cb93a386Sopenharmony_ci
133cb93a386Sopenharmony_ci	struct CubeBorderData
134cb93a386Sopenharmony_ci	{
135cb93a386Sopenharmony_ci		void *layers;
136cb93a386Sopenharmony_ci		uint32_t pitchB;
137cb93a386Sopenharmony_ci		uint32_t layerSize;
138cb93a386Sopenharmony_ci		uint32_t dim;
139cb93a386Sopenharmony_ci	};
140cb93a386Sopenharmony_ci
141cb93a386Sopenharmony_cipublic:
142cb93a386Sopenharmony_ci	Blitter();
143cb93a386Sopenharmony_ci	virtual ~Blitter();
144cb93a386Sopenharmony_ci
145cb93a386Sopenharmony_ci	void clear(const void *clearValue, vk::Format clearFormat, vk::Image *dest, const vk::Format &viewFormat, const VkImageSubresourceRange &subresourceRange, const VkRect2D *renderArea = nullptr);
146cb93a386Sopenharmony_ci
147cb93a386Sopenharmony_ci	void blit(const vk::Image *src, vk::Image *dst, VkImageBlit2KHR region, VkFilter filter);
148cb93a386Sopenharmony_ci	void resolve(const vk::Image *src, vk::Image *dst, VkImageResolve2KHR region);
149cb93a386Sopenharmony_ci	void resolveDepthStencil(const vk::ImageView *src, vk::ImageView *dst, const VkSubpassDescriptionDepthStencilResolve &dsrDesc);
150cb93a386Sopenharmony_ci	void copy(const vk::Image *src, uint8_t *dst, unsigned int dstPitch);
151cb93a386Sopenharmony_ci
152cb93a386Sopenharmony_ci	void updateBorders(const vk::Image *image, const VkImageSubresource &subresource);
153cb93a386Sopenharmony_ci
154cb93a386Sopenharmony_ciprivate:
155cb93a386Sopenharmony_ci	enum Edge
156cb93a386Sopenharmony_ci	{
157cb93a386Sopenharmony_ci		TOP,
158cb93a386Sopenharmony_ci		BOTTOM,
159cb93a386Sopenharmony_ci		RIGHT,
160cb93a386Sopenharmony_ci		LEFT
161cb93a386Sopenharmony_ci	};
162cb93a386Sopenharmony_ci
163cb93a386Sopenharmony_ci	bool fastClear(const void *clearValue, vk::Format clearFormat, vk::Image *dest, const vk::Format &viewFormat, const VkImageSubresourceRange &subresourceRange, const VkRect2D *renderArea);
164cb93a386Sopenharmony_ci	bool fastResolve(const vk::Image *src, vk::Image *dst, VkImageResolve2KHR region);
165cb93a386Sopenharmony_ci
166cb93a386Sopenharmony_ci	Float4 readFloat4(Pointer<Byte> element, const State &state);
167cb93a386Sopenharmony_ci	void write(Float4 &color, Pointer<Byte> element, const State &state);
168cb93a386Sopenharmony_ci	Int4 readInt4(Pointer<Byte> element, const State &state);
169cb93a386Sopenharmony_ci	void write(Int4 &color, Pointer<Byte> element, const State &state);
170cb93a386Sopenharmony_ci	static void ApplyScaleAndClamp(Float4 &value, const State &state, bool preScaled = false);
171cb93a386Sopenharmony_ci	static Int ComputeOffset(Int &x, Int &y, Int &pitchB, int bytes);
172cb93a386Sopenharmony_ci	static Int ComputeOffset(Int &x, Int &y, Int &z, Int &sliceB, Int &pitchB, int bytes);
173cb93a386Sopenharmony_ci	static Float4 LinearToSRGB(const Float4 &color);
174cb93a386Sopenharmony_ci	static Float4 sRGBtoLinear(const Float4 &color);
175cb93a386Sopenharmony_ci
176cb93a386Sopenharmony_ci	using BlitFunction = FunctionT<void(const BlitData *)>;
177cb93a386Sopenharmony_ci	using BlitRoutineType = BlitFunction::RoutineType;
178cb93a386Sopenharmony_ci	BlitRoutineType getBlitRoutine(const State &state);
179cb93a386Sopenharmony_ci	BlitRoutineType generate(const State &state);
180cb93a386Sopenharmony_ci	Float4 sample(Pointer<Byte> &source, Float &x, Float &y, Float &z,
181cb93a386Sopenharmony_ci	              Int &sWidth, Int &sHeight, Int &sDepth,
182cb93a386Sopenharmony_ci	              Int &sSliceB, Int &sPitchB, const State &state);
183cb93a386Sopenharmony_ci
184cb93a386Sopenharmony_ci	using CornerUpdateFunction = FunctionT<void(const CubeBorderData *)>;
185cb93a386Sopenharmony_ci	using CornerUpdateRoutineType = CornerUpdateFunction::RoutineType;
186cb93a386Sopenharmony_ci	CornerUpdateRoutineType getCornerUpdateRoutine(const State &state);
187cb93a386Sopenharmony_ci	CornerUpdateRoutineType generateCornerUpdate(const State &state);
188cb93a386Sopenharmony_ci	void computeCubeCorner(Pointer<Byte> &layer, Int &x0, Int &x1, Int &y0, Int &y1, Int &pitchB, const State &state);
189cb93a386Sopenharmony_ci
190cb93a386Sopenharmony_ci	void copyCubeEdge(const vk::Image *image,
191cb93a386Sopenharmony_ci	                  const VkImageSubresource &dstSubresource, Edge dstEdge,
192cb93a386Sopenharmony_ci	                  const VkImageSubresource &srcSubresource, Edge srcEdge);
193cb93a386Sopenharmony_ci
194cb93a386Sopenharmony_ci	marl::mutex blitMutex;
195cb93a386Sopenharmony_ci	RoutineCache<State, BlitFunction::CFunctionType> blitCache GUARDED_BY(blitMutex);
196cb93a386Sopenharmony_ci
197cb93a386Sopenharmony_ci	marl::mutex cornerUpdateMutex;
198cb93a386Sopenharmony_ci	RoutineCache<State, CornerUpdateFunction::CFunctionType> cornerUpdateCache GUARDED_BY(cornerUpdateMutex);
199cb93a386Sopenharmony_ci};
200cb93a386Sopenharmony_ci
201cb93a386Sopenharmony_ci}  // namespace sw
202cb93a386Sopenharmony_ci
203cb93a386Sopenharmony_cinamespace std {
204cb93a386Sopenharmony_ci
205cb93a386Sopenharmony_citemplate<>
206cb93a386Sopenharmony_cistruct hash<sw::Blitter::State>
207cb93a386Sopenharmony_ci{
208cb93a386Sopenharmony_ci	uint64_t operator()(const sw::Blitter::State &state) const
209cb93a386Sopenharmony_ci	{
210cb93a386Sopenharmony_ci		uint64_t hash = state.sourceFormat;
211cb93a386Sopenharmony_ci		hash = hash * 31 + state.destFormat;
212cb93a386Sopenharmony_ci		hash = hash * 31 + state.srcSamples;
213cb93a386Sopenharmony_ci		hash = hash * 31 + state.destSamples;
214cb93a386Sopenharmony_ci		hash = hash * 31 + state.filter3D;
215cb93a386Sopenharmony_ci		return hash;
216cb93a386Sopenharmony_ci	}
217cb93a386Sopenharmony_ci};
218cb93a386Sopenharmony_ci
219cb93a386Sopenharmony_ci}  // namespace std
220cb93a386Sopenharmony_ci
221cb93a386Sopenharmony_ci#endif  // sw_Blitter_hpp
222