Vulkan: Add wide-color 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, DE_NULL);
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::makeCurrent(void)
206 {
207         m_context->makeCurrent();
208 }
209
210 void FboRenderContext::createFramebuffer (const RenderConfig& config)
211 {
212         DE_ASSERT(m_framebuffer == 0 && m_colorBuffer == 0 && m_depthStencilBuffer == 0);
213
214         const glw::Functions&   gl                                      = m_context->getFunctions();
215         const deUint32                  colorFormat                     = chooseColorFormat(config);
216         const deUint32                  depthStencilFormat      = chooseDepthStencilFormat(config);
217         int                                             width                           = config.width;
218         int                                             height                          = config.height;
219         tcu::PixelFormat                pixelFormat;
220         int                                             depthBits                       = 0;
221         int                                             stencilBits                     = 0;
222
223         if (config.numSamples > 0 && !gl.renderbufferStorageMultisample)
224                 throw tcu::NotSupportedError("Multisample FBO is not supported");
225
226         if (colorFormat == 0)
227                 throw tcu::NotSupportedError("Unsupported color attachment format");
228
229         if (width == glu::RenderConfig::DONT_CARE || height == glu::RenderConfig::DONT_CARE)
230         {
231                 int maxSize = 0;
232                 gl.getIntegerv(GL_MAX_RENDERBUFFER_SIZE, &maxSize);
233
234                 width   = (width        == glu::RenderConfig::DONT_CARE) ? maxSize : width;
235                 height  = (height       == glu::RenderConfig::DONT_CARE) ? maxSize : height;
236         }
237
238         {
239                 pixelFormat = getPixelFormat(colorFormat);
240
241                 gl.genRenderbuffers(1, &m_colorBuffer);
242                 gl.bindRenderbuffer(GL_RENDERBUFFER, m_colorBuffer);
243
244                 if (config.numSamples > 0)
245                         gl.renderbufferStorageMultisample(GL_RENDERBUFFER, config.numSamples, colorFormat, width, height);
246                 else
247                         gl.renderbufferStorage(GL_RENDERBUFFER, colorFormat, width, height);
248
249                 gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
250                 GLU_EXPECT_NO_ERROR(gl.getError(), "Creating color renderbuffer");
251         }
252
253         if (depthStencilFormat != GL_NONE)
254         {
255                 getDepthStencilBits(depthStencilFormat, &depthBits, &stencilBits);
256
257                 gl.genRenderbuffers(1, &m_depthStencilBuffer);
258                 gl.bindRenderbuffer(GL_RENDERBUFFER, m_depthStencilBuffer);
259
260                 if (config.numSamples > 0)
261                         gl.renderbufferStorageMultisample(GL_RENDERBUFFER, config.numSamples, depthStencilFormat, width, height);
262                 else
263                         gl.renderbufferStorage(GL_RENDERBUFFER, depthStencilFormat, width, height);
264
265                 gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
266                 GLU_EXPECT_NO_ERROR(gl.getError(), "Creating depth / stencil renderbuffer");
267         }
268
269         gl.genFramebuffers(1, &m_framebuffer);
270         gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
271
272         if (m_colorBuffer)
273                 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_colorBuffer);
274
275         if (m_depthStencilBuffer)
276         {
277                 if (depthBits > 0)
278                         gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer);
279
280                 if (stencilBits > 0)
281                         gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer);
282         }
283
284         GLU_EXPECT_NO_ERROR(gl.getError(), "Creating framebuffer");
285
286         if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
287                 throw tcu::NotSupportedError("Framebuffer is not complete");
288
289         // Set up correct viewport for first test case.
290         gl.viewport(0, 0, width, height);
291
292         m_renderTarget = tcu::RenderTarget(width, height, pixelFormat, depthBits, stencilBits, config.numSamples);
293 }
294
295 void FboRenderContext::destroyFramebuffer (void)
296 {
297         const glw::Functions& gl = m_context->getFunctions();
298
299         if (m_framebuffer)
300         {
301                 gl.deleteFramebuffers(1, &m_framebuffer);
302                 m_framebuffer = 0;
303         }
304
305         if (m_depthStencilBuffer)
306         {
307                 gl.deleteRenderbuffers(1, &m_depthStencilBuffer);
308                 m_depthStencilBuffer = 0;
309         }
310
311         if (m_colorBuffer)
312         {
313                 gl.deleteRenderbuffers(1, &m_colorBuffer);
314                 m_colorBuffer = 0;
315         }
316 }
317
318 } // glu