1/*-------------------------------------------------------------------------
2 * drawElements Quality Program Reference Renderer
3 * -----------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Multisampled pixel buffer access
22 *//*--------------------------------------------------------------------*/
23
24#include "rrMultisamplePixelBufferAccess.hpp"
25#include "tcuTextureUtil.hpp"
26
27namespace rr
28{
29
30MultisamplePixelBufferAccess::MultisamplePixelBufferAccess (const tcu::PixelBufferAccess& rawAccess)
31	: m_access(rawAccess)
32{
33}
34
35MultisamplePixelBufferAccess::MultisamplePixelBufferAccess (void)
36	: m_access(tcu::PixelBufferAccess())
37{
38}
39
40const tcu::PixelBufferAccess MultisamplePixelBufferAccess::toSinglesampleAccess (void) const
41{
42	DE_ASSERT(getNumSamples() == 1);
43
44	return tcu::PixelBufferAccess(m_access.getFormat(),
45								  tcu::IVec3(m_access.getHeight(), m_access.getDepth(), 1),
46								  tcu::IVec3(m_access.getRowPitch(), m_access.getSlicePitch(), m_access.getSlicePitch() * m_access.getDepth()),
47								  m_access.getDataPtr());
48}
49
50MultisamplePixelBufferAccess MultisamplePixelBufferAccess::fromSinglesampleAccess (const tcu::PixelBufferAccess& original)
51{
52	return MultisamplePixelBufferAccess(
53				tcu::PixelBufferAccess(
54								original.getFormat(),
55								tcu::IVec3(1, original.getWidth(), original.getHeight()),
56								tcu::IVec3(original.getPixelPitch(), original.getPixelPitch(), original.getRowPitch()),
57								original.getDataPtr()));
58}
59
60MultisamplePixelBufferAccess MultisamplePixelBufferAccess::fromMultisampleAccess (const tcu::PixelBufferAccess& multisampledAccess)
61{
62	return MultisamplePixelBufferAccess(multisampledAccess);
63}
64
65MultisampleConstPixelBufferAccess::MultisampleConstPixelBufferAccess (void)
66	: m_access(tcu::ConstPixelBufferAccess())
67{
68}
69
70MultisampleConstPixelBufferAccess::MultisampleConstPixelBufferAccess (const tcu::ConstPixelBufferAccess& rawAccess)
71	: m_access(rawAccess)
72{
73}
74
75MultisampleConstPixelBufferAccess::MultisampleConstPixelBufferAccess (const rr::MultisamplePixelBufferAccess& msAccess)
76	: m_access(msAccess.raw())
77{
78}
79
80const tcu::ConstPixelBufferAccess MultisampleConstPixelBufferAccess::toSinglesampleAccess (void) const
81{
82	DE_ASSERT(getNumSamples() == 1);
83
84	return tcu::ConstPixelBufferAccess(m_access.getFormat(),
85									   tcu::IVec3(m_access.getHeight(), m_access.getDepth(), 1),
86									   tcu::IVec3(m_access.getRowPitch(), m_access.getSlicePitch(), m_access.getSlicePitch() * m_access.getDepth()),
87									   m_access.getDataPtr());
88}
89
90MultisampleConstPixelBufferAccess MultisampleConstPixelBufferAccess::fromSinglesampleAccess (const tcu::ConstPixelBufferAccess& original)
91{
92	return MultisampleConstPixelBufferAccess(
93				tcu::ConstPixelBufferAccess(
94								original.getFormat(),
95								tcu::IVec3(1, original.getWidth(), original.getHeight()),
96								tcu::IVec3(original.getPixelPitch(), original.getPixelPitch(), original.getRowPitch()),
97								original.getDataPtr()));
98}
99
100MultisampleConstPixelBufferAccess MultisampleConstPixelBufferAccess::fromMultisampleAccess (const tcu::ConstPixelBufferAccess& multisampledAccess)
101{
102	return MultisampleConstPixelBufferAccess(multisampledAccess);
103}
104
105MultisamplePixelBufferAccess getSubregion (const MultisamplePixelBufferAccess& access, int x, int y, int width, int height)
106{
107	return MultisamplePixelBufferAccess::fromMultisampleAccess(tcu::getSubregion(access.raw(), 0, x, y, access.getNumSamples(), width, height));
108}
109
110MultisampleConstPixelBufferAccess getSubregion (const MultisampleConstPixelBufferAccess& access, int x, int y, int width, int height)
111{
112	return MultisampleConstPixelBufferAccess::fromMultisampleAccess(tcu::getSubregion(access.raw(), 0, x, y, access.getNumSamples(), width, height));
113}
114
115void resolveMultisampleColorBuffer (const tcu::PixelBufferAccess& dst, const MultisampleConstPixelBufferAccess& src)
116{
117	DE_ASSERT(dst.getWidth() == src.raw().getHeight());
118	DE_ASSERT(dst.getHeight() == src.raw().getDepth());
119
120	if (src.getNumSamples() == 1)
121	{
122		// fast-path for non-multisampled cases
123		tcu::copy(dst, src.toSinglesampleAccess());
124	}
125	else
126	{
127		const float numSamplesInv = 1.0f / (float)src.getNumSamples();
128
129		for (int y = 0; y < dst.getHeight(); y++)
130		for (int x = 0; x < dst.getWidth(); x++)
131		{
132			tcu::Vec4 sum;
133			for (int s = 0; s < src.raw().getWidth(); s++)
134				sum += src.raw().getPixel(s, x, y);
135
136			dst.setPixel(sum*numSamplesInv, x, y);
137		}
138	}
139}
140
141void resolveMultisampleDepthBuffer (const tcu::PixelBufferAccess& dst, const MultisampleConstPixelBufferAccess& src)
142{
143	DE_ASSERT(dst.getWidth() == src.raw().getHeight());
144	DE_ASSERT(dst.getHeight() == src.raw().getDepth());
145
146	const tcu::ConstPixelBufferAccess	effectiveSrc = tcu::getEffectiveDepthStencilAccess(src.raw(), tcu::Sampler::MODE_DEPTH);
147	const tcu::PixelBufferAccess		effectiveDst = tcu::getEffectiveDepthStencilAccess(dst, tcu::Sampler::MODE_DEPTH);
148
149	if (src.getNumSamples() == 1)
150	{
151		// fast-path for non-multisampled cases
152		tcu::copy(effectiveDst, MultisampleConstPixelBufferAccess::fromMultisampleAccess(effectiveSrc).toSinglesampleAccess());
153	}
154	else
155	{
156		const float numSamplesInv = 1.0f / (float)src.getNumSamples();
157
158		for (int y = 0; y < dst.getHeight(); y++)
159		for (int x = 0; x < dst.getWidth(); x++)
160		{
161			float sum = 0.0f;
162			for (int s = 0; s < src.getNumSamples(); s++)
163				sum += effectiveSrc.getPixDepth(s, x, y);
164
165			effectiveDst.setPixDepth(sum*numSamplesInv, x, y);
166		}
167	}
168}
169
170void resolveMultisampleStencilBuffer (const tcu::PixelBufferAccess& dst, const MultisampleConstPixelBufferAccess& src)
171{
172	DE_ASSERT(dst.getWidth() == src.raw().getHeight());
173	DE_ASSERT(dst.getHeight() == src.raw().getDepth());
174
175	const tcu::ConstPixelBufferAccess	effectiveSrc = tcu::getEffectiveDepthStencilAccess(src.raw(), tcu::Sampler::MODE_STENCIL);
176	const tcu::PixelBufferAccess		effectiveDst = tcu::getEffectiveDepthStencilAccess(dst, tcu::Sampler::MODE_STENCIL);
177
178	if (src.getNumSamples() == 1)
179	{
180		// fast-path for non-multisampled cases
181		tcu::copy(effectiveDst, MultisampleConstPixelBufferAccess::fromMultisampleAccess(effectiveSrc).toSinglesampleAccess());
182	}
183	else
184	{
185		// Resolve by selecting one
186		for (int y = 0; y < dst.getHeight(); y++)
187		for (int x = 0; x < dst.getWidth(); x++)
188			effectiveDst.setPixStencil(effectiveSrc.getPixStencil(0, x, y), x, y);
189	}
190}
191
192void resolveMultisampleBuffer (const tcu::PixelBufferAccess& dst, const MultisampleConstPixelBufferAccess& src)
193{
194	switch (src.raw().getFormat().order)
195	{
196		case tcu::TextureFormat::D:
197			resolveMultisampleDepthBuffer(dst, src);
198			return;
199
200		case tcu::TextureFormat::S:
201			resolveMultisampleStencilBuffer(dst, src);
202			return;
203
204		case tcu::TextureFormat::DS:
205			resolveMultisampleDepthBuffer(dst, src);
206			resolveMultisampleStencilBuffer(dst, src);
207			return;
208
209		default:
210			resolveMultisampleColorBuffer(dst, src);
211			return;
212	}
213}
214
215tcu::Vec4 resolveMultisamplePixel (const MultisampleConstPixelBufferAccess& access, int x, int y)
216{
217	tcu::Vec4 sum;
218	for (int s = 0; s < access.getNumSamples(); s++)
219		sum += access.raw().getPixel(s, x, y);
220
221	return sum / (float)access.getNumSamples();
222}
223
224void clear (const MultisamplePixelBufferAccess& access, const tcu::Vec4& color)
225{
226	tcu::clear(access.raw(), color);
227}
228
229void clear (const MultisamplePixelBufferAccess& access, const tcu::IVec4& color)
230{
231	tcu::clear(access.raw(), color);
232}
233
234void clearDepth (const MultisamplePixelBufferAccess& access, float depth)
235{
236	tcu::clearDepth(access.raw(), depth);
237}
238
239void clearStencil (const MultisamplePixelBufferAccess& access, int stencil)
240{
241	tcu::clearStencil(access.raw(), stencil);
242}
243
244} // rr
245