CP: Fix required sample count tests
[platform/upstream/VK-GL-CTS.git] / framework / opengl / gluFboRenderContext.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES Utilities
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 OpenGL ES context wrapper that uses FBO as default framebuffer.
22  *//*--------------------------------------------------------------------*/
23
24 #include "gluFboRenderContext.hpp"
25 #include "gluContextFactory.hpp"
26 #include "gluRenderConfig.hpp"
27 #include "glwEnums.hpp"
28 #include "glwFunctions.hpp"
29 #include "tcuCommandLine.hpp"
30 #include "gluTextureUtil.hpp"
31 #include "tcuTextureUtil.hpp"
32
33 #include <sstream>
34
35 namespace glu
36 {
37
38 static int getNumDepthBits (const tcu::TextureFormat& format)
39 {
40         if (format.order == tcu::TextureFormat::DS)
41         {
42                 const tcu::TextureFormat        depthOnlyFormat         = tcu::getEffectiveDepthStencilTextureFormat(format, tcu::Sampler::MODE_DEPTH);
43                 return tcu::getTextureFormatBitDepth(depthOnlyFormat).x();
44         }
45         else if (format.order == tcu::TextureFormat::D)
46                 return tcu::getTextureFormatBitDepth(format).x();
47         else
48                 return 0;
49 }
50
51 static int getNumStencilBits (const tcu::TextureFormat& format)
52 {
53         if (format.order == tcu::TextureFormat::DS)
54         {
55                 const tcu::TextureFormat        stencilOnlyFormat               = tcu::getEffectiveDepthStencilTextureFormat(format, tcu::Sampler::MODE_STENCIL);
56                 return tcu::getTextureFormatBitDepth(stencilOnlyFormat).x();
57         }
58         else if (format.order == tcu::TextureFormat::S)
59                 return tcu::getTextureFormatBitDepth(format).x();
60         else
61                 return 0;
62 }
63
64 static tcu::PixelFormat getPixelFormat (deUint32 colorFormat)
65 {
66         const tcu::IVec4 bits = tcu::getTextureFormatBitDepth(glu::mapGLInternalFormat(colorFormat));
67         return tcu::PixelFormat(bits[0], bits[1], bits[2], bits[3]);
68 }
69
70 static void getDepthStencilBits (deUint32 depthStencilFormat, int* depthBits, int* stencilBits)
71 {
72         const tcu::TextureFormat        combinedFormat  = glu::mapGLInternalFormat(depthStencilFormat);
73
74         *depthBits              = getNumDepthBits(combinedFormat);
75         *stencilBits    = getNumStencilBits(combinedFormat);
76 }
77
78 deUint32 chooseColorFormat (const glu::RenderConfig& config)
79 {
80         static const deUint32 s_formats[] =
81         {
82                 GL_RGBA8,
83                 GL_RGB8,
84                 GL_RG8,
85                 GL_R8,
86                 GL_RGBA4,
87                 GL_RGB5_A1,
88                 GL_RGB565,
89                 GL_RGB5
90         };
91
92         for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(s_formats); fmtNdx++)
93         {
94                 const deUint32          format  = s_formats[fmtNdx];
95                 const tcu::IVec4        bits    = tcu::getTextureFormatBitDepth(glu::mapGLInternalFormat(format));
96
97                 if (config.redBits != glu::RenderConfig::DONT_CARE &&
98                         config.redBits != bits[0])
99                         continue;
100
101                 if (config.greenBits != glu::RenderConfig::DONT_CARE &&
102                         config.greenBits != bits[1])
103                         continue;
104
105                 if (config.blueBits != glu::RenderConfig::DONT_CARE &&
106                         config.blueBits != bits[2])
107                         continue;
108
109                 if (config.alphaBits != glu::RenderConfig::DONT_CARE &&
110                         config.alphaBits != bits[3])
111                         continue;
112
113                 return format;
114         }
115
116         return 0;
117 }
118
119 deUint32 chooseDepthStencilFormat (const glu::RenderConfig& config)
120 {
121         static const deUint32 s_formats[] =
122         {
123                 GL_DEPTH32F_STENCIL8,
124                 GL_DEPTH24_STENCIL8,
125                 GL_DEPTH_COMPONENT32F,
126                 GL_DEPTH_COMPONENT24,
127                 GL_DEPTH_COMPONENT16,
128                 GL_STENCIL_INDEX8
129         };
130
131         for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(s_formats); fmtNdx++)
132         {
133                 const deUint32                          format                  = s_formats[fmtNdx];
134                 const tcu::TextureFormat        combinedFormat  = glu::mapGLInternalFormat(format);
135                 const int                                       depthBits               = getNumDepthBits(combinedFormat);
136                 const int                                       stencilBits             = getNumStencilBits(combinedFormat);
137
138                 if (config.depthBits != glu::RenderConfig::DONT_CARE &&
139                         config.depthBits != depthBits)
140                         continue;
141
142                 if (config.stencilBits != glu::RenderConfig::DONT_CARE &&
143                         config.stencilBits != stencilBits)
144                         continue;
145
146                 return format;
147         }
148
149         return 0;
150 }
151
152 FboRenderContext::FboRenderContext (RenderContext* context, const RenderConfig& config)
153         : m_context                             (context)
154         , m_framebuffer                 (0)
155         , m_colorBuffer                 (0)
156         , m_depthStencilBuffer  (0)
157         , m_renderTarget                ()
158 {
159         try
160         {
161                 createFramebuffer(config);
162         }
163         catch (...)
164         {
165                 destroyFramebuffer();
166                 throw;
167         }
168 }
169
170 FboRenderContext::FboRenderContext (const ContextFactory& factory, const RenderConfig& config, const tcu::CommandLine& cmdLine)
171         : m_context                             (DE_NULL)
172         , m_framebuffer                 (0)
173         , m_colorBuffer                 (0)
174         , m_depthStencilBuffer  (0)
175         , m_renderTarget                ()
176 {
177         try
178         {
179                 RenderConfig nativeRenderConfig;
180                 nativeRenderConfig.type                         = config.type;
181                 nativeRenderConfig.windowVisibility     = config.windowVisibility;
182                 // \note All other properties are defaults, mostly DONT_CARE
183                 m_context = factory.createContext(nativeRenderConfig, cmdLine);
184                 createFramebuffer(config);
185         }
186         catch (...)
187         {
188                 delete m_context;
189                 throw;
190         }
191 }
192
193 FboRenderContext::~FboRenderContext (void)
194 {
195         // \todo [2013-04-08 pyry] Do we want to destry FBO before destroying context?
196         delete m_context;
197 }
198
199 void FboRenderContext::postIterate (void)
200 {
201         // \todo [2012-11-27 pyry] Blit to default framebuffer in ES3?
202         m_context->getFunctions().finish();
203 }
204
205 void FboRenderContext::createFramebuffer (const RenderConfig& config)
206 {
207         DE_ASSERT(m_framebuffer == 0 && m_colorBuffer == 0 && m_depthStencilBuffer == 0);
208
209         const glw::Functions&   gl                                      = m_context->getFunctions();
210         const deUint32                  colorFormat                     = chooseColorFormat(config);
211         const deUint32                  depthStencilFormat      = chooseDepthStencilFormat(config);
212         int                                             width                           = config.width;
213         int                                             height                          = config.height;
214         tcu::PixelFormat                pixelFormat;
215         int                                             depthBits                       = 0;
216         int                                             stencilBits                     = 0;
217
218         if (config.numSamples > 0 && !gl.renderbufferStorageMultisample)
219                 throw tcu::NotSupportedError("Multisample FBO is not supported");
220
221         if (colorFormat == 0)
222                 throw tcu::NotSupportedError("Unsupported color attachment format");
223
224         if (width == glu::RenderConfig::DONT_CARE || height == glu::RenderConfig::DONT_CARE)
225         {
226                 int maxSize = 0;
227                 gl.getIntegerv(GL_MAX_RENDERBUFFER_SIZE, &maxSize);
228
229                 width   = (width        == glu::RenderConfig::DONT_CARE) ? maxSize : width;
230                 height  = (height       == glu::RenderConfig::DONT_CARE) ? maxSize : height;
231         }
232
233         {
234                 pixelFormat = getPixelFormat(colorFormat);
235
236                 gl.genRenderbuffers(1, &m_colorBuffer);
237                 gl.bindRenderbuffer(GL_RENDERBUFFER, m_colorBuffer);
238
239                 if (config.numSamples > 0)
240                         gl.renderbufferStorageMultisample(GL_RENDERBUFFER, config.numSamples, colorFormat, width, height);
241                 else
242                         gl.renderbufferStorage(GL_RENDERBUFFER, colorFormat, width, height);
243
244                 gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
245                 GLU_EXPECT_NO_ERROR(gl.getError(), "Creating color renderbuffer");
246         }
247
248         if (depthStencilFormat != GL_NONE)
249         {
250                 getDepthStencilBits(depthStencilFormat, &depthBits, &stencilBits);
251
252                 gl.genRenderbuffers(1, &m_depthStencilBuffer);
253                 gl.bindRenderbuffer(GL_RENDERBUFFER, m_depthStencilBuffer);
254
255                 if (config.numSamples > 0)
256                         gl.renderbufferStorageMultisample(GL_RENDERBUFFER, config.numSamples, depthStencilFormat, width, height);
257                 else
258                         gl.renderbufferStorage(GL_RENDERBUFFER, depthStencilFormat, width, height);
259
260                 gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
261                 GLU_EXPECT_NO_ERROR(gl.getError(), "Creating depth / stencil renderbuffer");
262         }
263
264         gl.genFramebuffers(1, &m_framebuffer);
265         gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
266
267         if (m_colorBuffer)
268                 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_colorBuffer);
269
270         if (m_depthStencilBuffer)
271         {
272                 if (depthBits > 0)
273                         gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer);
274
275                 if (stencilBits > 0)
276                         gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer);
277         }
278
279         GLU_EXPECT_NO_ERROR(gl.getError(), "Creating framebuffer");
280
281         if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
282                 throw tcu::NotSupportedError("Framebuffer is not complete");
283
284         // Set up correct viewport for first test case.
285         gl.viewport(0, 0, width, height);
286
287         m_renderTarget = tcu::RenderTarget(width, height, pixelFormat, depthBits, stencilBits, config.numSamples);
288 }
289
290 void FboRenderContext::destroyFramebuffer (void)
291 {
292         const glw::Functions& gl = m_context->getFunctions();
293
294         if (m_framebuffer)
295         {
296                 gl.deleteFramebuffers(1, &m_framebuffer);
297                 m_framebuffer = 0;
298         }
299
300         if (m_depthStencilBuffer)
301         {
302                 gl.deleteRenderbuffers(1, &m_depthStencilBuffer);
303                 m_depthStencilBuffer = 0;
304         }
305
306         if (m_colorBuffer)
307         {
308                 gl.deleteRenderbuffers(1, &m_colorBuffer);
309                 m_colorBuffer = 0;
310         }
311 }
312
313 } // glu