Fix missing dependency on sparse binds
[platform/upstream/VK-GL-CTS.git] / framework / opengl / simplereference / sglrReferenceContext.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 Reference Rendering Context.
22  *//*--------------------------------------------------------------------*/
23
24 #include "sglrReferenceContext.hpp"
25 #include "sglrReferenceUtils.hpp"
26 #include "sglrShaderProgram.hpp"
27 #include "tcuTextureUtil.hpp"
28 #include "tcuMatrix.hpp"
29 #include "tcuMatrixUtil.hpp"
30 #include "tcuVectorUtil.hpp"
31 #include "gluDefs.hpp"
32 #include "gluTextureUtil.hpp"
33 #include "gluContextInfo.hpp"
34 #include "glwFunctions.hpp"
35 #include "glwEnums.hpp"
36 #include "deMemory.h"
37 #include "rrFragmentOperations.hpp"
38 #include "rrRenderer.hpp"
39
40 #include <cstdint>
41
42 namespace sglr
43 {
44
45 using std::vector;
46 using std::map;
47
48 using tcu::Vec2;
49 using tcu::Vec3;
50 using tcu::Vec4;
51 using tcu::IVec2;
52 using tcu::IVec4;
53 using tcu::RGBA;
54
55 // Reference context implementation
56 using namespace rc;
57
58 using tcu::TextureFormat;
59 using tcu::PixelBufferAccess;
60 using tcu::ConstPixelBufferAccess;
61
62 // Utilities for ReferenceContext
63 #define RC_RET_VOID
64
65 #define RC_ERROR_RET(ERR, RET)                  \
66 do {                                                                    \
67         setError(ERR);                                          \
68         return RET;                                                     \
69 } while (deGetFalse())
70
71 #define RC_IF_ERROR(COND, ERR, RET)             \
72 do {                                                                    \
73         if (COND)                                                       \
74                 RC_ERROR_RET(ERR, RET);                 \
75 } while (deGetFalse())
76
77 static inline tcu::PixelBufferAccess nullAccess (void)
78 {
79         return tcu::PixelBufferAccess(TextureFormat(TextureFormat::R, TextureFormat::UNSIGNED_INT8), 0, 0, 0, DE_NULL);
80 }
81
82 static inline bool isEmpty (const tcu::ConstPixelBufferAccess& access)
83 {
84         return access.getWidth() == 0 || access.getHeight() == 0 || access.getDepth() == 0;
85 }
86
87 static inline bool isEmpty (const rr::MultisampleConstPixelBufferAccess& access)
88 {
89         return access.raw().getWidth() == 0 || access.raw().getHeight() == 0 || access.raw().getDepth() == 0;
90 }
91
92 static inline bool isEmpty (const IVec4& rect)
93 {
94         return rect.z() == 0 || rect.w() == 0;
95 }
96
97 inline int getNumMipLevels1D (int size)
98 {
99         return deLog2Floor32(size)+1;
100 }
101
102 inline int getNumMipLevels2D (int width, int height)
103 {
104         return deLog2Floor32(de::max(width, height))+1;
105 }
106
107 inline int getNumMipLevels3D (int width, int height, int depth)
108 {
109         return deLog2Floor32(de::max(width, de::max(height, depth)))+1;
110 }
111
112 inline int getMipLevelSize (int baseLevelSize, int levelNdx)
113 {
114         return de::max(baseLevelSize >> levelNdx, 1);
115 }
116
117 inline bool isMipmapFilter (const tcu::Sampler::FilterMode mode)
118 {
119         return mode != tcu::Sampler::NEAREST && mode != tcu::Sampler::LINEAR;
120 }
121
122 static tcu::CubeFace texTargetToFace (Framebuffer::TexTarget target)
123 {
124         switch (target)
125         {
126                 case Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_X:        return tcu::CUBEFACE_NEGATIVE_X;
127                 case Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_X:        return tcu::CUBEFACE_POSITIVE_X;
128                 case Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_Y:        return tcu::CUBEFACE_NEGATIVE_Y;
129                 case Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_Y:        return tcu::CUBEFACE_POSITIVE_Y;
130                 case Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_Z:        return tcu::CUBEFACE_NEGATIVE_Z;
131                 case Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_Z:        return tcu::CUBEFACE_POSITIVE_Z;
132                 default:                                                                                        return tcu::CUBEFACE_LAST;
133         }
134 }
135
136 static Framebuffer::TexTarget texLayeredTypeToTarget (Texture::Type type)
137 {
138         switch (type)
139         {
140                 case Texture::TYPE_2D_ARRAY:            return Framebuffer::TEXTARGET_2D_ARRAY;
141                 case Texture::TYPE_3D:                          return Framebuffer::TEXTARGET_3D;
142                 case Texture::TYPE_CUBE_MAP_ARRAY:      return Framebuffer::TEXTARGET_CUBE_MAP_ARRAY;
143                 default:                                                        return Framebuffer::TEXTARGET_LAST;
144         }
145 }
146
147 static tcu::CubeFace mapGLCubeFace (deUint32 face)
148 {
149         switch (face)
150         {
151                 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:    return tcu::CUBEFACE_NEGATIVE_X;
152                 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:    return tcu::CUBEFACE_POSITIVE_X;
153                 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:    return tcu::CUBEFACE_NEGATIVE_Y;
154                 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:    return tcu::CUBEFACE_POSITIVE_Y;
155                 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:    return tcu::CUBEFACE_NEGATIVE_Z;
156                 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:    return tcu::CUBEFACE_POSITIVE_Z;
157                 default:                                                                return tcu::CUBEFACE_LAST;
158         }
159 }
160
161 tcu::TextureFormat toTextureFormat (const tcu::PixelFormat& pixelFmt)
162 {
163         static const struct
164         {
165                 tcu::PixelFormat        pixelFmt;
166                 tcu::TextureFormat      texFmt;
167         } pixelFormatMap[] =
168         {
169                 { tcu::PixelFormat(8,8,8,8),    tcu::TextureFormat(tcu::TextureFormat::RGBA,    tcu::TextureFormat::UNORM_INT8)                 },
170                 { tcu::PixelFormat(8,8,8,0),    tcu::TextureFormat(tcu::TextureFormat::RGB,             tcu::TextureFormat::UNORM_INT8)                 },
171                 { tcu::PixelFormat(4,4,4,4),    tcu::TextureFormat(tcu::TextureFormat::RGBA,    tcu::TextureFormat::UNORM_SHORT_4444)   },
172                 { tcu::PixelFormat(5,5,5,1),    tcu::TextureFormat(tcu::TextureFormat::RGBA,    tcu::TextureFormat::UNORM_SHORT_5551)   },
173                 { tcu::PixelFormat(5,6,5,0),    tcu::TextureFormat(tcu::TextureFormat::RGB,             tcu::TextureFormat::UNORM_SHORT_565)    }
174         };
175
176         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pixelFormatMap); ndx++)
177         {
178                 if (pixelFormatMap[ndx].pixelFmt == pixelFmt)
179                         return pixelFormatMap[ndx].texFmt;
180         }
181
182         TCU_FAIL("Can't map pixel format to texture format");
183 }
184
185 tcu::TextureFormat toNonSRGBFormat (const tcu::TextureFormat& fmt)
186 {
187         switch (fmt.order)
188         {
189                 case tcu::TextureFormat::sRGB:
190                         return tcu::TextureFormat(tcu::TextureFormat::RGB,      fmt.type);
191                 case tcu::TextureFormat::sRGBA:
192                         return tcu::TextureFormat(tcu::TextureFormat::RGBA,     fmt.type);
193                 default:
194                         return fmt;
195         }
196 }
197
198 tcu::TextureFormat getDepthFormat (int depthBits)
199 {
200         switch (depthBits)
201         {
202                 case 8:         return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT8);
203                 case 16:        return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT16);
204                 case 24:        return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNSIGNED_INT_24_8);
205                 case 32:        return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::FLOAT);
206                 default:
207                         TCU_FAIL("Can't map depth buffer format");
208         }
209 }
210
211 tcu::TextureFormat getStencilFormat (int stencilBits)
212 {
213         switch (stencilBits)
214         {
215                 case 8:         return tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT8);
216                 case 16:        return tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT16);
217                 case 24:        return tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT_24_8);
218                 case 32:        return tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT32);
219                 default:
220                         TCU_FAIL("Can't map depth buffer format");
221         }
222 }
223
224 static inline tcu::IVec4 intersect (const tcu::IVec4& a, const tcu::IVec4& b)
225 {
226         int             x0      = de::max(a.x(), b.x());
227         int             y0      = de::max(a.y(), b.y());
228         int             x1      = de::min(a.x()+a.z(), b.x()+b.z());
229         int             y1      = de::min(a.y()+a.w(), b.y()+b.w());
230         int             w       = de::max(0, x1-x0);
231         int             h       = de::max(0, y1-y0);
232
233         return tcu::IVec4(x0, y0, w, h);
234 }
235
236 static inline tcu::IVec4 getBufferRect (const rr::MultisampleConstPixelBufferAccess& access)
237 {
238         return tcu::IVec4(0, 0, access.raw().getHeight(), access.raw().getDepth());
239 }
240
241 ReferenceContextLimits::ReferenceContextLimits (const glu::RenderContext& renderCtx)
242         : contextType                           (renderCtx.getType())
243         , maxTextureImageUnits          (0)
244         , maxTexture2DSize                      (0)
245         , maxTextureCubeSize            (0)
246         , maxTexture2DArrayLayers       (0)
247         , maxTexture3DSize                      (0)
248         , maxRenderbufferSize           (0)
249         , maxVertexAttribs                      (0)
250         , subpixelBits                          (0)
251 {
252         const glw::Functions& gl = renderCtx.getFunctions();
253
254         // When the OpenGL ES's major version bigger than 3, and the expect context version is 3,
255         // we need query the real GL context version and update the real version to reference context.
256         if (glu::IsES3Compatible(gl) && isES2Context(contextType))
257         {
258                 int majorVersion = contextType.getMajorVersion();
259                 int minorVersion = contextType.getMinorVersion();
260                 gl.getIntegerv(GL_MAJOR_VERSION, &majorVersion);
261                 gl.getIntegerv(GL_MINOR_VERSION, &minorVersion);
262                 contextType.setAPI(glu::ApiType::es(majorVersion, minorVersion));
263         }
264
265         gl.getIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS,              &maxTextureImageUnits);
266         gl.getIntegerv(GL_MAX_TEXTURE_SIZE,                             &maxTexture2DSize);
267         gl.getIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE,    &maxTextureCubeSize);
268         gl.getIntegerv(GL_MAX_RENDERBUFFER_SIZE,                &maxRenderbufferSize);
269         gl.getIntegerv(GL_MAX_VERTEX_ATTRIBS,                   &maxVertexAttribs);
270         gl.getIntegerv(GL_SUBPIXEL_BITS,                                &subpixelBits);
271
272         if (contextSupports(contextType, glu::ApiType::es(3,0)) || glu::isContextTypeGLCore(contextType))
273         {
274                 gl.getIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS,     &maxTexture2DArrayLayers);
275                 gl.getIntegerv(GL_MAX_3D_TEXTURE_SIZE,          &maxTexture3DSize);
276         }
277
278         // Limit texture sizes to supported values
279         maxTexture2DSize        = de::min(maxTexture2DSize,             (int)MAX_TEXTURE_SIZE);
280         maxTextureCubeSize      = de::min(maxTextureCubeSize,   (int)MAX_TEXTURE_SIZE);
281         maxTexture3DSize        = de::min(maxTexture3DSize,             (int)MAX_TEXTURE_SIZE);
282
283         GLU_EXPECT_NO_ERROR(gl.getError(), GL_NO_ERROR);
284
285         // \todo [pyry] Figure out following things:
286         // + supported fbo configurations
287         // ...
288
289         // \todo [2013-08-01 pyry] Do we want to make these conditional based on renderCtx?
290         addExtension("GL_EXT_color_buffer_half_float");
291         addExtension("GL_EXT_color_buffer_float");
292
293         if (contextSupports(contextType, glu::ApiType::es(3,1)))
294                 addExtension("GL_EXT_texture_cube_map_array");
295 }
296
297 void ReferenceContextLimits::addExtension (const char* extension)
298 {
299         extensionList.push_back(extension);
300
301         if (!extensionStr.empty())
302                 extensionStr += " ";
303         extensionStr += extension;
304 }
305
306 ReferenceContextBuffers::ReferenceContextBuffers (const tcu::PixelFormat& colorBits, int depthBits, int stencilBits, int width, int height, int samples)
307 {
308         m_colorbuffer.setStorage(toTextureFormat(colorBits), samples, width, height);
309
310         if (depthBits > 0)
311                 m_depthbuffer.setStorage(getDepthFormat(depthBits), samples, width, height);
312
313         if (stencilBits > 0)
314                 m_stencilbuffer.setStorage(getStencilFormat(stencilBits), samples, width, height);
315 }
316
317 ReferenceContext::StencilState::StencilState (void)
318         : func                          (GL_ALWAYS)
319         , ref                           (0)
320         , opMask                        (~0u)
321         , opStencilFail         (GL_KEEP)
322         , opDepthFail           (GL_KEEP)
323         , opDepthPass           (GL_KEEP)
324         , writeMask                     (~0u)
325 {
326 }
327
328 ReferenceContext::ReferenceContext (const ReferenceContextLimits& limits, const rr::MultisamplePixelBufferAccess& colorbuffer, const rr::MultisamplePixelBufferAccess& depthbuffer, const rr::MultisamplePixelBufferAccess& stencilbuffer)
329         : Context                                                       (limits.contextType)
330         , m_limits                                                      (limits)
331         , m_defaultColorbuffer                          (colorbuffer)
332         , m_defaultDepthbuffer                          (depthbuffer)
333         , m_defaultStencilbuffer                        (stencilbuffer)
334         , m_clientVertexArray                           (0, m_limits.maxVertexAttribs)
335
336         , m_viewport                                            (0, 0, colorbuffer.raw().getHeight(), colorbuffer.raw().getDepth())
337
338         , m_activeTexture                                       (0)
339         , m_textureUnits                                        (m_limits.maxTextureImageUnits)
340         , m_emptyTex1D                                          ()
341         , m_emptyTex2D                                          (isES2Context(limits.contextType))
342         , m_emptyTexCube                                        (!isES2Context(limits.contextType))
343         , m_emptyTex2DArray                                     ()
344         , m_emptyTex3D                                          ()
345         , m_emptyTexCubeArray                           ()
346
347         , m_pixelUnpackRowLength                        (0)
348         , m_pixelUnpackSkipRows                         (0)
349         , m_pixelUnpackSkipPixels                       (0)
350         , m_pixelUnpackImageHeight                      (0)
351         , m_pixelUnpackSkipImages                       (0)
352         , m_pixelUnpackAlignment                        (4)
353         , m_pixelPackAlignment                          (4)
354
355         , m_readFramebufferBinding                      (DE_NULL)
356         , m_drawFramebufferBinding                      (DE_NULL)
357         , m_renderbufferBinding                         (DE_NULL)
358         , m_vertexArrayBinding                          (DE_NULL)
359         , m_currentProgram                                      (DE_NULL)
360
361         , m_arrayBufferBinding                          (DE_NULL)
362         , m_pixelPackBufferBinding                      (DE_NULL)
363         , m_pixelUnpackBufferBinding            (DE_NULL)
364         , m_transformFeedbackBufferBinding      (DE_NULL)
365         , m_uniformBufferBinding                        (DE_NULL)
366         , m_copyReadBufferBinding                       (DE_NULL)
367         , m_copyWriteBufferBinding                      (DE_NULL)
368         , m_drawIndirectBufferBinding           (DE_NULL)
369
370         , m_clearColor                                          (0.0f, 0.0f, 0.0f, 0.0f)
371         , m_clearDepth                                          (1.0f)
372         , m_clearStencil                                        (0)
373         , m_scissorEnabled                                      (false)
374         , m_scissorBox                                          (m_viewport)
375         , m_stencilTestEnabled                          (false)
376         , m_depthTestEnabled                            (false)
377         , m_depthFunc                                           (GL_LESS)
378         , m_depthRangeNear                                      (0.0f)
379         , m_depthRangeFar                                       (1.0f)
380         , m_polygonOffsetFactor                         (0.0f)
381         , m_polygonOffsetUnits                          (0.0f)
382         , m_polygonOffsetFillEnabled            (false)
383         , m_provokingFirstVertexConvention      (false)
384         , m_blendEnabled                                        (false)
385         , m_blendModeRGB                                        (GL_FUNC_ADD)
386         , m_blendModeAlpha                                      (GL_FUNC_ADD)
387         , m_blendFactorSrcRGB                           (GL_ONE)
388         , m_blendFactorDstRGB                           (GL_ZERO)
389         , m_blendFactorSrcAlpha                         (GL_ONE)
390         , m_blendFactorDstAlpha                         (GL_ZERO)
391         , m_blendColor                                          (0.0f, 0.0f, 0.0f, 0.0f)
392         , m_sRGBUpdateEnabled                           (true)
393         , m_depthClampEnabled                           (false)
394         , m_colorMask                                           (true, true, true, true)
395         , m_depthMask                                           (true)
396         , m_currentAttribs                                      (m_limits.maxVertexAttribs, rr::GenericVec4(tcu::Vec4(0, 0, 0, 1)))
397         , m_lineWidth                                           (1.0f)
398         , m_primitiveRestartFixedIndex          (false)
399         , m_primitiveRestartSettableIndex       (false)
400         , m_primitiveRestartIndex                       (0)
401
402         , m_lastError                                           (GL_NO_ERROR)
403 {
404         // Create empty textures to be used when texture objects are incomplete.
405         m_emptyTex1D.getSampler().wrapS         = tcu::Sampler::CLAMP_TO_EDGE;
406         m_emptyTex1D.getSampler().wrapT         = tcu::Sampler::CLAMP_TO_EDGE;
407         m_emptyTex1D.getSampler().minFilter     = tcu::Sampler::NEAREST;
408         m_emptyTex1D.getSampler().magFilter     = tcu::Sampler::NEAREST;
409         m_emptyTex1D.allocLevel(0, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1);
410         m_emptyTex1D.getLevel(0).setPixel(Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0);
411         m_emptyTex1D.updateView(tcu::Sampler::MODE_LAST);
412
413         m_emptyTex2D.getSampler().wrapS         = tcu::Sampler::CLAMP_TO_EDGE;
414         m_emptyTex2D.getSampler().wrapT         = tcu::Sampler::CLAMP_TO_EDGE;
415         m_emptyTex2D.getSampler().minFilter     = tcu::Sampler::NEAREST;
416         m_emptyTex2D.getSampler().magFilter     = tcu::Sampler::NEAREST;
417         m_emptyTex2D.allocLevel(0, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1, 1);
418         m_emptyTex2D.getLevel(0).setPixel(Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0);
419         m_emptyTex2D.updateView(tcu::Sampler::MODE_LAST);
420
421         m_emptyTexCube.getSampler().wrapS               = tcu::Sampler::CLAMP_TO_EDGE;
422         m_emptyTexCube.getSampler().wrapT               = tcu::Sampler::CLAMP_TO_EDGE;
423         m_emptyTexCube.getSampler().minFilter   = tcu::Sampler::NEAREST;
424         m_emptyTexCube.getSampler().magFilter   = tcu::Sampler::NEAREST;
425         for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
426         {
427                 m_emptyTexCube.allocFace(0, (tcu::CubeFace)face, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1, 1);
428                 m_emptyTexCube.getFace(0, (tcu::CubeFace)face).setPixel(Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0);
429         }
430         m_emptyTexCube.updateView(tcu::Sampler::MODE_LAST);
431
432         m_emptyTex2DArray.getSampler().wrapS            = tcu::Sampler::CLAMP_TO_EDGE;
433         m_emptyTex2DArray.getSampler().wrapT            = tcu::Sampler::CLAMP_TO_EDGE;
434         m_emptyTex2DArray.getSampler().minFilter        = tcu::Sampler::NEAREST;
435         m_emptyTex2DArray.getSampler().magFilter        = tcu::Sampler::NEAREST;
436         m_emptyTex2DArray.allocLevel(0, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1, 1, 1);
437         m_emptyTex2DArray.getLevel(0).setPixel(Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0);
438         m_emptyTex2DArray.updateView(tcu::Sampler::MODE_LAST);
439
440         m_emptyTex3D.getSampler().wrapS         = tcu::Sampler::CLAMP_TO_EDGE;
441         m_emptyTex3D.getSampler().wrapT         = tcu::Sampler::CLAMP_TO_EDGE;
442         m_emptyTex3D.getSampler().wrapR         = tcu::Sampler::CLAMP_TO_EDGE;
443         m_emptyTex3D.getSampler().minFilter     = tcu::Sampler::NEAREST;
444         m_emptyTex3D.getSampler().magFilter     = tcu::Sampler::NEAREST;
445         m_emptyTex3D.allocLevel(0, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1, 1, 1);
446         m_emptyTex3D.getLevel(0).setPixel(Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0);
447         m_emptyTex3D.updateView(tcu::Sampler::MODE_LAST);
448
449         m_emptyTexCubeArray.getSampler().wrapS          = tcu::Sampler::CLAMP_TO_EDGE;
450         m_emptyTexCubeArray.getSampler().wrapT          = tcu::Sampler::CLAMP_TO_EDGE;
451         m_emptyTexCubeArray.getSampler().minFilter      = tcu::Sampler::NEAREST;
452         m_emptyTexCubeArray.getSampler().magFilter      = tcu::Sampler::NEAREST;
453         m_emptyTexCubeArray.allocLevel(0, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 1, 1, 6);
454         for (int faceNdx = 0; faceNdx < 6; faceNdx++)
455                 m_emptyTexCubeArray.getLevel(0).setPixel(Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0, faceNdx);
456         m_emptyTexCubeArray.updateView(tcu::Sampler::MODE_LAST);
457
458         for (int unitNdx = 0; unitNdx < m_limits.maxTextureImageUnits; unitNdx++)
459                 m_textureUnits[unitNdx].defaultCubeTex.getSampler().seamlessCubeMap = !isES2Context(limits.contextType);
460
461         if (glu::isContextTypeGLCore(getType()))
462                 m_sRGBUpdateEnabled = false;
463 }
464
465 ReferenceContext::~ReferenceContext (void)
466 {
467         // Destroy all objects -- verifies that ref counting works
468         {
469                 vector<VertexArray*> vertexArrays;
470                 m_vertexArrays.getAll(vertexArrays);
471                 for (vector<VertexArray*>::iterator i = vertexArrays.begin(); i != vertexArrays.end(); i++)
472                         deleteVertexArray(*i);
473
474                 DE_ASSERT(m_clientVertexArray.getRefCount() == 1);
475         }
476
477         {
478                 vector<Texture*> textures;
479                 m_textures.getAll(textures);
480                 for (vector<Texture*>::iterator i = textures.begin(); i != textures.end(); i++)
481                         deleteTexture(*i);
482         }
483
484         {
485                 vector<Framebuffer*> framebuffers;
486                 m_framebuffers.getAll(framebuffers);
487                 for (vector<Framebuffer*>::iterator i = framebuffers.begin(); i != framebuffers.end(); i++)
488                         deleteFramebuffer(*i);
489         }
490
491         {
492                 vector<Renderbuffer*> renderbuffers;
493                 m_renderbuffers.getAll(renderbuffers);
494                 for (vector<Renderbuffer*>::iterator i = renderbuffers.begin(); i != renderbuffers.end(); i++)
495                         deleteRenderbuffer(*i);
496         }
497
498         {
499                 vector<DataBuffer*> buffers;
500                 m_buffers.getAll(buffers);
501                 for (vector<DataBuffer*>::iterator i = buffers.begin(); i != buffers.end(); i++)
502                         deleteBuffer(*i);
503         }
504
505         {
506                 vector<ShaderProgramObjectContainer*> programs;
507                 m_programs.getAll(programs);
508                 for (vector<ShaderProgramObjectContainer*>::iterator i = programs.begin(); i != programs.end(); i++)
509                         deleteProgramObject(*i);
510         }
511 }
512
513 void ReferenceContext::activeTexture (deUint32 texture)
514 {
515         if (deInBounds32(texture, GL_TEXTURE0, GL_TEXTURE0 + (deUint32)m_textureUnits.size()))
516                 m_activeTexture = texture - GL_TEXTURE0;
517         else
518                 setError(GL_INVALID_ENUM);
519 }
520
521 void ReferenceContext::setTex1DBinding (int unitNdx, Texture1D* texture)
522 {
523         if (m_textureUnits[unitNdx].tex1DBinding)
524         {
525                 m_textures.releaseReference(m_textureUnits[unitNdx].tex1DBinding);
526                 m_textureUnits[unitNdx].tex1DBinding = DE_NULL;
527         }
528
529         if (texture)
530         {
531                 m_textures.acquireReference(texture);
532                 m_textureUnits[unitNdx].tex1DBinding = texture;
533         }
534 }
535
536 void ReferenceContext::setTex2DBinding (int unitNdx, Texture2D* texture)
537 {
538         if (m_textureUnits[unitNdx].tex2DBinding)
539         {
540                 m_textures.releaseReference(m_textureUnits[unitNdx].tex2DBinding);
541                 m_textureUnits[unitNdx].tex2DBinding = DE_NULL;
542         }
543
544         if (texture)
545         {
546                 m_textures.acquireReference(texture);
547                 m_textureUnits[unitNdx].tex2DBinding = texture;
548         }
549 }
550
551 void ReferenceContext::setTexCubeBinding (int unitNdx, TextureCube* texture)
552 {
553         if (m_textureUnits[unitNdx].texCubeBinding)
554         {
555                 m_textures.releaseReference(m_textureUnits[unitNdx].texCubeBinding);
556                 m_textureUnits[unitNdx].texCubeBinding = DE_NULL;
557         }
558
559         if (texture)
560         {
561                 m_textures.acquireReference(texture);
562                 m_textureUnits[unitNdx].texCubeBinding = texture;
563         }
564 }
565
566 void ReferenceContext::setTex2DArrayBinding (int unitNdx, Texture2DArray* texture)
567 {
568         if (m_textureUnits[unitNdx].tex2DArrayBinding)
569         {
570                 m_textures.releaseReference(m_textureUnits[unitNdx].tex2DArrayBinding);
571                 m_textureUnits[unitNdx].tex2DArrayBinding = DE_NULL;
572         }
573
574         if (texture)
575         {
576                 m_textures.acquireReference(texture);
577                 m_textureUnits[unitNdx].tex2DArrayBinding = texture;
578         }
579 }
580
581 void ReferenceContext::setTex3DBinding (int unitNdx, Texture3D* texture)
582 {
583         if (m_textureUnits[unitNdx].tex3DBinding)
584         {
585                 m_textures.releaseReference(m_textureUnits[unitNdx].tex3DBinding);
586                 m_textureUnits[unitNdx].tex3DBinding = DE_NULL;
587         }
588
589         if (texture)
590         {
591                 m_textures.acquireReference(texture);
592                 m_textureUnits[unitNdx].tex3DBinding = texture;
593         }
594 }
595
596 void ReferenceContext::setTexCubeArrayBinding (int unitNdx, TextureCubeArray* texture)
597 {
598         if (m_textureUnits[unitNdx].texCubeArrayBinding)
599         {
600                 m_textures.releaseReference(m_textureUnits[unitNdx].texCubeArrayBinding);
601                 m_textureUnits[unitNdx].texCubeArrayBinding = DE_NULL;
602         }
603
604         if (texture)
605         {
606                 m_textures.acquireReference(texture);
607                 m_textureUnits[unitNdx].texCubeArrayBinding = texture;
608         }
609 }
610
611 void ReferenceContext::bindTexture (deUint32 target, deUint32 texture)
612 {
613         int unitNdx = m_activeTexture;
614
615         RC_IF_ERROR(target != GL_TEXTURE_1D                             &&
616                                 target != GL_TEXTURE_2D                         &&
617                                 target != GL_TEXTURE_CUBE_MAP           &&
618                                 target != GL_TEXTURE_2D_ARRAY           &&
619                                 target != GL_TEXTURE_3D                         &&
620                                 target != GL_TEXTURE_CUBE_MAP_ARRAY,
621                                 GL_INVALID_ENUM, RC_RET_VOID);
622
623         RC_IF_ERROR(glu::isContextTypeES(m_limits.contextType) && (target == GL_TEXTURE_1D), GL_INVALID_ENUM, RC_RET_VOID);
624
625         if (texture == 0)
626         {
627                 // Clear binding.
628                 switch (target)
629                 {
630                         case GL_TEXTURE_1D:                             setTex1DBinding                 (unitNdx, DE_NULL);     break;
631                         case GL_TEXTURE_2D:                             setTex2DBinding                 (unitNdx, DE_NULL);     break;
632                         case GL_TEXTURE_CUBE_MAP:               setTexCubeBinding               (unitNdx, DE_NULL);     break;
633                         case GL_TEXTURE_2D_ARRAY:               setTex2DArrayBinding    (unitNdx, DE_NULL);     break;
634                         case GL_TEXTURE_3D:                             setTex3DBinding                 (unitNdx, DE_NULL);     break;
635                         case GL_TEXTURE_CUBE_MAP_ARRAY: setTexCubeArrayBinding  (unitNdx, DE_NULL);     break;
636                         default:
637                                 DE_ASSERT(false);
638                 }
639         }
640         else
641         {
642                 Texture* texObj = m_textures.find(texture);
643
644                 if (texObj)
645                 {
646                         // Validate type.
647                         Texture::Type expectedType = Texture::TYPE_LAST;
648                         switch (target)
649                         {
650                                 case GL_TEXTURE_1D:                             expectedType = Texture::TYPE_1D;                                break;
651                                 case GL_TEXTURE_2D:                             expectedType = Texture::TYPE_2D;                                break;
652                                 case GL_TEXTURE_CUBE_MAP:               expectedType = Texture::TYPE_CUBE_MAP;                  break;
653                                 case GL_TEXTURE_2D_ARRAY:               expectedType = Texture::TYPE_2D_ARRAY;                  break;
654                                 case GL_TEXTURE_3D:                             expectedType = Texture::TYPE_3D;                                break;
655                                 case GL_TEXTURE_CUBE_MAP_ARRAY: expectedType = Texture::TYPE_CUBE_MAP_ARRAY;    break;
656                                 default:
657                                         DE_ASSERT(false);
658                         }
659                         RC_IF_ERROR(texObj->getType() != expectedType, GL_INVALID_OPERATION, RC_RET_VOID);
660                 }
661                 else
662                 {
663                         // New texture object.
664                         bool seamlessCubeMap = !isES2Context(m_limits.contextType);
665                         switch (target)
666                         {
667                                 case GL_TEXTURE_1D:                             texObj = new Texture1D                  (texture);                                      break;
668                                 case GL_TEXTURE_2D:                             texObj = new Texture2D                  (texture);                                      break;
669                                 case GL_TEXTURE_CUBE_MAP:               texObj = new TextureCube                (texture, seamlessCubeMap);     break;
670                                 case GL_TEXTURE_2D_ARRAY:               texObj = new Texture2DArray             (texture);                                      break;
671                                 case GL_TEXTURE_3D:                             texObj = new Texture3D                  (texture);                                      break;
672                                 case GL_TEXTURE_CUBE_MAP_ARRAY: texObj = new TextureCubeArray   (texture);                                      break;
673                                 default:
674                                         DE_ASSERT(false);
675                         }
676
677                         m_textures.insert(texObj);
678                 }
679
680                 switch (target)
681                 {
682                         case GL_TEXTURE_1D:                             setTex1DBinding                 (unitNdx, static_cast<Texture1D*>                       (texObj));      break;
683                         case GL_TEXTURE_2D:                             setTex2DBinding                 (unitNdx, static_cast<Texture2D*>                       (texObj));      break;
684                         case GL_TEXTURE_CUBE_MAP:               setTexCubeBinding               (unitNdx, static_cast<TextureCube*>                     (texObj));      break;
685                         case GL_TEXTURE_2D_ARRAY:               setTex2DArrayBinding    (unitNdx, static_cast<Texture2DArray*>          (texObj));      break;
686                         case GL_TEXTURE_3D:                             setTex3DBinding                 (unitNdx, static_cast<Texture3D*>                       (texObj));      break;
687                         case GL_TEXTURE_CUBE_MAP_ARRAY: setTexCubeArrayBinding  (unitNdx, static_cast<TextureCubeArray*>        (texObj));      break;
688                         default:
689                                 DE_ASSERT(false);
690                 }
691         }
692 }
693
694 void ReferenceContext::genTextures (int numTextures, deUint32* textures)
695 {
696         while (numTextures--)
697                 *textures++ = m_textures.allocateName();
698 }
699
700 void ReferenceContext::deleteTextures (int numTextures, const deUint32* textures)
701 {
702         for (int i = 0; i < numTextures; i++)
703         {
704                 deUint32        name            = textures[i];
705                 Texture*        texture         = name ? m_textures.find(name) : DE_NULL;
706
707                 if (texture)
708                         deleteTexture(texture);
709         }
710 }
711
712 void ReferenceContext::deleteTexture (Texture* texture)
713 {
714         // Unbind from context
715         for (int unitNdx = 0; unitNdx < (int)m_textureUnits.size(); unitNdx++)
716         {
717                 if (m_textureUnits[unitNdx].tex1DBinding                                == texture)     setTex1DBinding                 (unitNdx, DE_NULL);
718                 else if (m_textureUnits[unitNdx].tex2DBinding                   == texture)     setTex2DBinding                 (unitNdx, DE_NULL);
719                 else if (m_textureUnits[unitNdx].texCubeBinding                 == texture)     setTexCubeBinding               (unitNdx, DE_NULL);
720                 else if (m_textureUnits[unitNdx].tex2DArrayBinding              == texture)     setTex2DArrayBinding    (unitNdx, DE_NULL);
721                 else if (m_textureUnits[unitNdx].tex3DBinding                   == texture)     setTex3DBinding                 (unitNdx, DE_NULL);
722                 else if (m_textureUnits[unitNdx].texCubeArrayBinding    == texture)     setTexCubeArrayBinding  (unitNdx, DE_NULL);
723         }
724
725         // Unbind from currently bound framebuffers
726         for (int ndx = 0; ndx < 2; ndx++)
727         {
728                 rc::Framebuffer* framebufferBinding = ndx ? m_drawFramebufferBinding : m_readFramebufferBinding;
729                 if (framebufferBinding)
730                 {
731                         int releaseRefCount = (framebufferBinding == m_drawFramebufferBinding ? 1 : 0)
732                                                                 + (framebufferBinding == m_readFramebufferBinding ? 1 : 0);
733
734                         for (int point = 0; point < Framebuffer::ATTACHMENTPOINT_LAST; point++)
735                         {
736                                 Framebuffer::Attachment& attachment = framebufferBinding->getAttachment((Framebuffer::AttachmentPoint)point);
737                                 if (attachment.name == texture->getName())
738                                 {
739                                         for (int refNdx = 0; refNdx < releaseRefCount; refNdx++)
740                                                 releaseFboAttachmentReference(attachment);
741                                         attachment = Framebuffer::Attachment();
742                                 }
743                         }
744                 }
745         }
746
747         DE_ASSERT(texture->getRefCount() == 1);
748         m_textures.releaseReference(texture);
749 }
750
751 void ReferenceContext::bindFramebuffer (deUint32 target, deUint32 name)
752 {
753         Framebuffer* fbo = DE_NULL;
754
755         RC_IF_ERROR(target != GL_FRAMEBUFFER            &&
756                                 target != GL_DRAW_FRAMEBUFFER   &&
757                                 target != GL_READ_FRAMEBUFFER, GL_INVALID_ENUM, RC_RET_VOID);
758
759         if (name != 0)
760         {
761                 // Find or create framebuffer object.
762                 fbo = m_framebuffers.find(name);
763                 if (!fbo)
764                 {
765                         fbo = new Framebuffer(name);
766                         m_framebuffers.insert(fbo);
767                 }
768         }
769
770         for (int ndx = 0; ndx < 2; ndx++)
771         {
772                 deUint32                        bindingTarget   = ndx ? GL_DRAW_FRAMEBUFFER                     : GL_READ_FRAMEBUFFER;
773                 rc::Framebuffer*&       binding                 = ndx ? m_drawFramebufferBinding        : m_readFramebufferBinding;
774
775                 if (target != GL_FRAMEBUFFER && target != bindingTarget)
776                         continue; // Doesn't match this target.
777
778                 // Remove old references
779                 if (binding)
780                 {
781                         // Clear all attachment point references
782                         for (int point = 0; point < Framebuffer::ATTACHMENTPOINT_LAST; point++)
783                                 releaseFboAttachmentReference(binding->getAttachment((Framebuffer::AttachmentPoint)point));
784
785                         m_framebuffers.releaseReference(binding);
786                 }
787
788                 // Create new references
789                 if (fbo)
790                 {
791                         m_framebuffers.acquireReference(fbo);
792
793                         for (int point = 0; point < Framebuffer::ATTACHMENTPOINT_LAST; point++)
794                                 acquireFboAttachmentReference(fbo->getAttachment((Framebuffer::AttachmentPoint)point));
795                 }
796
797                 binding = fbo;
798         }
799 }
800
801 void ReferenceContext::genFramebuffers (int numFramebuffers, deUint32* framebuffers)
802 {
803         while (numFramebuffers--)
804                 *framebuffers++ = m_framebuffers.allocateName();
805 }
806
807 void ReferenceContext::deleteFramebuffer (Framebuffer* framebuffer)
808 {
809         // Remove bindings.
810         if (m_drawFramebufferBinding == framebuffer) bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
811         if (m_readFramebufferBinding == framebuffer) bindFramebuffer(GL_READ_FRAMEBUFFER, 0);
812
813         DE_ASSERT(framebuffer->getRefCount() == 1);
814         m_framebuffers.releaseReference(framebuffer);
815 }
816
817 void ReferenceContext::deleteFramebuffers (int numFramebuffers, const deUint32* framebuffers)
818 {
819         for (int i = 0; i < numFramebuffers; i++)
820         {
821                 deUint32                name            = framebuffers[i];
822                 Framebuffer*    framebuffer     = name ? m_framebuffers.find(name) : DE_NULL;
823
824                 if (framebuffer)
825                         deleteFramebuffer(framebuffer);
826         }
827 }
828
829 void ReferenceContext::bindRenderbuffer (deUint32 target, deUint32 name)
830 {
831         Renderbuffer* rbo = DE_NULL;
832
833         RC_IF_ERROR(target != GL_RENDERBUFFER, GL_INVALID_ENUM, RC_RET_VOID);
834
835         if (name != 0)
836         {
837                 rbo = m_renderbuffers.find(name);
838                 if (!rbo)
839                 {
840                         rbo = new Renderbuffer(name);
841                         m_renderbuffers.insert(rbo);
842                 }
843         }
844
845         // Remove old reference
846         if (m_renderbufferBinding)
847                 m_renderbuffers.releaseReference(m_renderbufferBinding);
848
849         // Create new reference
850         if (rbo)
851                 m_renderbuffers.acquireReference(rbo);
852
853         m_renderbufferBinding = rbo;
854 }
855
856 void ReferenceContext::genRenderbuffers (int numRenderbuffers, deUint32* renderbuffers)
857 {
858         while (numRenderbuffers--)
859                 *renderbuffers++ = m_renderbuffers.allocateName();
860 }
861
862 void ReferenceContext::deleteRenderbuffer (Renderbuffer* renderbuffer)
863 {
864         if (m_renderbufferBinding == renderbuffer)
865                 bindRenderbuffer(GL_RENDERBUFFER, 0);
866
867         // Unbind from currently bound framebuffers
868         for (int ndx = 0; ndx < 2; ndx++)
869         {
870                 rc::Framebuffer* framebufferBinding = ndx ? m_drawFramebufferBinding : m_readFramebufferBinding;
871                 if (framebufferBinding)
872                 {
873                         int releaseRefCount = (framebufferBinding == m_drawFramebufferBinding ? 1 : 0)
874                                                                 + (framebufferBinding == m_readFramebufferBinding ? 1 : 0);
875
876                         for (int point = 0; point < Framebuffer::ATTACHMENTPOINT_LAST; point++)
877                         {
878                                 Framebuffer::Attachment& attachment = framebufferBinding->getAttachment((Framebuffer::AttachmentPoint)point);
879                                 if (attachment.name == renderbuffer->getName())
880                                 {
881                                         for (int refNdx = 0; refNdx < releaseRefCount; refNdx++)
882                                                 releaseFboAttachmentReference(attachment);
883                                         attachment = Framebuffer::Attachment();
884                                 }
885                         }
886                 }
887         }
888
889         DE_ASSERT(renderbuffer->getRefCount() == 1);
890         m_renderbuffers.releaseReference(renderbuffer);
891 }
892
893 void ReferenceContext::deleteRenderbuffers (int numRenderbuffers, const deUint32* renderbuffers)
894 {
895         for (int i = 0; i < numRenderbuffers; i++)
896         {
897                 deUint32                name                    = renderbuffers[i];
898                 Renderbuffer*   renderbuffer    = name ? m_renderbuffers.find(name) : DE_NULL;
899
900                 if (renderbuffer)
901                         deleteRenderbuffer(renderbuffer);
902         }
903 }
904
905 void ReferenceContext::pixelStorei (deUint32 pname, int param)
906 {
907         switch (pname)
908         {
909                 case GL_UNPACK_ALIGNMENT:
910                         RC_IF_ERROR(param != 1 && param != 2 && param != 4 && param != 8, GL_INVALID_VALUE, RC_RET_VOID);
911                         m_pixelUnpackAlignment = param;
912                         break;
913
914                 case GL_PACK_ALIGNMENT:
915                         RC_IF_ERROR(param != 1 && param != 2 && param != 4 && param != 8, GL_INVALID_VALUE, RC_RET_VOID);
916                         m_pixelPackAlignment = param;
917                         break;
918
919                 case GL_UNPACK_ROW_LENGTH:
920                         RC_IF_ERROR(param < 0, GL_INVALID_VALUE, RC_RET_VOID);
921                         m_pixelUnpackRowLength = param;
922                         break;
923
924                 case GL_UNPACK_SKIP_ROWS:
925                         RC_IF_ERROR(param < 0, GL_INVALID_VALUE, RC_RET_VOID);
926                         m_pixelUnpackSkipRows = param;
927                         break;
928
929                 case GL_UNPACK_SKIP_PIXELS:
930                         RC_IF_ERROR(param < 0, GL_INVALID_VALUE, RC_RET_VOID);
931                         m_pixelUnpackSkipPixels = param;
932                         break;
933
934                 case GL_UNPACK_IMAGE_HEIGHT:
935                         RC_IF_ERROR(param < 0, GL_INVALID_VALUE, RC_RET_VOID);
936                         m_pixelUnpackImageHeight = param;
937                         break;
938
939                 case GL_UNPACK_SKIP_IMAGES:
940                         RC_IF_ERROR(param < 0, GL_INVALID_VALUE, RC_RET_VOID);
941                         m_pixelUnpackSkipImages = param;
942                         break;
943
944                 default:
945                         setError(GL_INVALID_ENUM);
946         }
947 }
948
949 tcu::ConstPixelBufferAccess ReferenceContext::getUnpack2DAccess (const tcu::TextureFormat& format, int width, int height, const void* data)
950 {
951         int                             pixelSize       = format.getPixelSize();
952         int                             rowLen          = m_pixelUnpackRowLength > 0 ? m_pixelUnpackRowLength : width;
953         int                             rowPitch        = deAlign32(rowLen*pixelSize, m_pixelUnpackAlignment);
954         const deUint8*  ptr                     = (const deUint8*)data + m_pixelUnpackSkipRows*rowPitch + m_pixelUnpackSkipPixels*pixelSize;
955
956         return tcu::ConstPixelBufferAccess(format, width, height, 1, rowPitch, 0, ptr);
957 }
958
959 tcu::ConstPixelBufferAccess ReferenceContext::getUnpack3DAccess (const tcu::TextureFormat& format, int width, int height, int depth, const void* data)
960 {
961         int                             pixelSize       = format.getPixelSize();
962         int                             rowLen          = m_pixelUnpackRowLength        > 0 ? m_pixelUnpackRowLength    : width;
963         int                             imageHeight     = m_pixelUnpackImageHeight      > 0 ? m_pixelUnpackImageHeight  : height;
964         int                             rowPitch        = deAlign32(rowLen*pixelSize, m_pixelUnpackAlignment);
965         int                             slicePitch      = imageHeight*rowPitch;
966         const deUint8*  ptr                     = (const deUint8*)data + m_pixelUnpackSkipImages*slicePitch + m_pixelUnpackSkipRows*rowPitch + m_pixelUnpackSkipPixels*pixelSize;
967
968         return tcu::ConstPixelBufferAccess(format, width, height, depth, rowPitch, slicePitch, ptr);
969 }
970
971 static tcu::TextureFormat mapInternalFormat (deUint32 internalFormat)
972 {
973         switch (internalFormat)
974         {
975                 case GL_ALPHA:                          return TextureFormat(TextureFormat::A,          TextureFormat::UNORM_INT8);
976                 case GL_LUMINANCE:                      return TextureFormat(TextureFormat::L,          TextureFormat::UNORM_INT8);
977                 case GL_LUMINANCE_ALPHA:        return TextureFormat(TextureFormat::LA,         TextureFormat::UNORM_INT8);
978                 case GL_RGB:                            return TextureFormat(TextureFormat::RGB,        TextureFormat::UNORM_INT8);
979                 case GL_RGBA:                           return TextureFormat(TextureFormat::RGBA,       TextureFormat::UNORM_INT8);
980
981                 default:
982                         return glu::mapGLInternalFormat(internalFormat);
983         }
984 }
985
986 static void depthValueFloatClampCopy (const PixelBufferAccess& dst, const ConstPixelBufferAccess& src)
987 {
988         int width       = dst.getWidth();
989         int height      = dst.getHeight();
990         int depth       = dst.getDepth();
991
992         DE_ASSERT(src.getWidth() == width && src.getHeight() == height && src.getDepth() == depth);
993
994         // clamping copy
995
996         if (src.getFormat().order == tcu::TextureFormat::DS && dst.getFormat().order == tcu::TextureFormat::DS)
997         {
998                 // copy only depth and stencil
999                 for (int z = 0; z < depth; z++)
1000                 for (int y = 0; y < height; y++)
1001                 for (int x = 0; x < width; x++)
1002                 {
1003                         dst.setPixDepth(de::clamp(src.getPixDepth(x, y, z), 0.0f, 1.0f), x, y, z);
1004                         dst.setPixStencil(src.getPixStencil(x, y, z), x, y, z);
1005                 }
1006         }
1007         else
1008         {
1009                 // copy only depth
1010                 for (int z = 0; z < depth; z++)
1011                 for (int y = 0; y < height; y++)
1012                 for (int x = 0; x < width; x++)
1013                         dst.setPixDepth(de::clamp(src.getPixDepth(x, y, z), 0.0f, 1.0f), x, y, z);
1014         }
1015 }
1016
1017 void ReferenceContext::texImage1D (deUint32 target, int level, deUint32 internalFormat, int width, int border, deUint32 format, deUint32 type, const void* data)
1018 {
1019         texImage2D(target, level, internalFormat, width, 1, border, format, type, data);
1020 }
1021
1022 void ReferenceContext::texImage2D (deUint32 target, int level, deUint32 internalFormat, int width, int height, int border, deUint32 format, deUint32 type, const void* data)
1023 {
1024         texImage3D(target, level, internalFormat, width, height, 1, border, format, type, data);
1025 }
1026
1027 static void clearToTextureInitialValue (PixelBufferAccess access)
1028 {
1029         const bool hasDepth             = access.getFormat().order == tcu::TextureFormat::D || access.getFormat().order == tcu::TextureFormat::DS;
1030         const bool hasStencil   = access.getFormat().order == tcu::TextureFormat::S || access.getFormat().order == tcu::TextureFormat::DS;
1031         const bool hasColor             = !hasDepth && !hasStencil;
1032
1033         if (hasDepth)
1034                 tcu::clearDepth(access, 0.0f);
1035         if (hasStencil)
1036                 tcu::clearStencil(access, 0u);
1037         if (hasColor)
1038                 tcu::clear(access, Vec4(0.0f, 0.0f, 0.0f, 1.0f));
1039 }
1040
1041 void ReferenceContext::texImage3D (deUint32 target, int level, deUint32 internalFormat, int width, int height, int depth, int border, deUint32 format, deUint32 type, const void* data)
1042 {
1043         TextureUnit&            unit                                    = m_textureUnits[m_activeTexture];
1044         const void*                     unpackPtr                               = getPixelUnpackPtr(data);
1045         const bool                      isDstFloatDepthFormat   = (internalFormat == GL_DEPTH_COMPONENT32F || internalFormat == GL_DEPTH32F_STENCIL8); // depth components are limited to [0,1] range
1046         TextureFormat           storageFmt;
1047         TextureFormat           transferFmt;
1048
1049         RC_IF_ERROR(border != 0, GL_INVALID_VALUE, RC_RET_VOID);
1050         RC_IF_ERROR(width < 0 || height < 0 || depth < 0 || level < 0, GL_INVALID_VALUE, RC_RET_VOID);
1051
1052         // Map storage format.
1053         storageFmt = mapInternalFormat(internalFormat);
1054         RC_IF_ERROR(storageFmt.order    == TextureFormat::CHANNELORDER_LAST ||
1055                                 storageFmt.type         == TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
1056
1057         // Map transfer format.
1058         transferFmt = glu::mapGLTransferFormat(format, type);
1059         RC_IF_ERROR(transferFmt.order   == TextureFormat::CHANNELORDER_LAST ||
1060                                 transferFmt.type        == TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
1061
1062         if (target == GL_TEXTURE_1D && glu::isContextTypeGLCore(m_limits.contextType))
1063         {
1064                 // Validate size and level.
1065                 RC_IF_ERROR(width > m_limits.maxTexture2DSize || height != 1 || depth != 1, GL_INVALID_VALUE, RC_RET_VOID);
1066                 RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture2DSize), GL_INVALID_VALUE, RC_RET_VOID);
1067
1068                 Texture1D* texture = unit.tex1DBinding ? unit.tex1DBinding : &unit.default1DTex;
1069
1070                 if (texture->isImmutable())
1071                 {
1072                         RC_IF_ERROR(!texture->hasLevel(level), GL_INVALID_OPERATION, RC_RET_VOID);
1073
1074                         ConstPixelBufferAccess dst(texture->getLevel(level));
1075                         RC_IF_ERROR(storageFmt  != dst.getFormat()      ||
1076                                                 width           != dst.getWidth(), GL_INVALID_OPERATION, RC_RET_VOID);
1077                 }
1078                 else
1079                         texture->allocLevel(level, storageFmt, width);
1080
1081                 if (unpackPtr)
1082                 {
1083                         ConstPixelBufferAccess  src             = getUnpack2DAccess(transferFmt, width, 1, unpackPtr);
1084                         PixelBufferAccess               dst             (texture->getLevel(level));
1085
1086                         if (isDstFloatDepthFormat)
1087                                 depthValueFloatClampCopy(dst, src);
1088                         else
1089                                 tcu::copy(dst, src);
1090                 }
1091                 else
1092                 {
1093                         // No data supplied, clear to initial
1094                         clearToTextureInitialValue(texture->getLevel(level));
1095                 }
1096         }
1097         else if (target == GL_TEXTURE_2D)
1098         {
1099                 // Validate size and level.
1100                 RC_IF_ERROR(width > m_limits.maxTexture2DSize || height > m_limits.maxTexture2DSize || depth != 1, GL_INVALID_VALUE, RC_RET_VOID);
1101                 RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture2DSize), GL_INVALID_VALUE, RC_RET_VOID);
1102
1103                 Texture2D* texture = unit.tex2DBinding ? unit.tex2DBinding : &unit.default2DTex;
1104
1105                 if (texture->isImmutable())
1106                 {
1107                         RC_IF_ERROR(!texture->hasLevel(level), GL_INVALID_OPERATION, RC_RET_VOID);
1108
1109                         ConstPixelBufferAccess dst(texture->getLevel(level));
1110                         RC_IF_ERROR(storageFmt  != dst.getFormat()      ||
1111                                                 width           != dst.getWidth()       ||
1112                                                 height          != dst.getHeight(), GL_INVALID_OPERATION, RC_RET_VOID);
1113                 }
1114                 else
1115                         texture->allocLevel(level, storageFmt, width, height);
1116
1117                 if (unpackPtr)
1118                 {
1119                         ConstPixelBufferAccess  src             = getUnpack2DAccess(transferFmt, width, height, unpackPtr);
1120                         PixelBufferAccess               dst             (texture->getLevel(level));
1121
1122                         if (isDstFloatDepthFormat)
1123                                 depthValueFloatClampCopy(dst, src);
1124                         else
1125                                 tcu::copy(dst, src);
1126                 }
1127                 else
1128                 {
1129                         // No data supplied, clear to initial
1130                         clearToTextureInitialValue(texture->getLevel(level));
1131                 }
1132         }
1133         else if (target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
1134                          target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
1135                          target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
1136                          target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
1137                          target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z ||
1138                          target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z)
1139         {
1140                 // Validate size and level.
1141                 RC_IF_ERROR(width != height || width > m_limits.maxTextureCubeSize || depth != 1, GL_INVALID_VALUE, RC_RET_VOID);
1142                 RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTextureCubeSize), GL_INVALID_VALUE, RC_RET_VOID);
1143
1144                 TextureCube*    texture = unit.texCubeBinding ? unit.texCubeBinding : &unit.defaultCubeTex;
1145                 tcu::CubeFace   face    = mapGLCubeFace(target);
1146
1147                 if (texture->isImmutable())
1148                 {
1149                         RC_IF_ERROR(!texture->hasFace(level, face), GL_INVALID_OPERATION, RC_RET_VOID);
1150
1151                         ConstPixelBufferAccess dst(texture->getFace(level, face));
1152                         RC_IF_ERROR(storageFmt  != dst.getFormat()      ||
1153                                                 width           != dst.getWidth()       ||
1154                                                 height          != dst.getHeight(), GL_INVALID_OPERATION, RC_RET_VOID);
1155                 }
1156                 else
1157                         texture->allocFace(level, face, storageFmt, width, height);
1158
1159                 if (unpackPtr)
1160                 {
1161                         ConstPixelBufferAccess  src             = getUnpack2DAccess(transferFmt, width, height, unpackPtr);
1162                         PixelBufferAccess               dst             (texture->getFace(level, face));
1163
1164                         if (isDstFloatDepthFormat)
1165                                 depthValueFloatClampCopy(dst, src);
1166                         else
1167                                 tcu::copy(dst, src);
1168                 }
1169                 else
1170                 {
1171                         // No data supplied, clear to initial
1172                         clearToTextureInitialValue(texture->getFace(level, face));
1173                 }
1174         }
1175         else if (target == GL_TEXTURE_2D_ARRAY)
1176         {
1177                 // Validate size and level.
1178                 RC_IF_ERROR(width       > m_limits.maxTexture2DSize ||
1179                                         height  > m_limits.maxTexture2DSize ||
1180                                         depth   > m_limits.maxTexture2DArrayLayers, GL_INVALID_VALUE, RC_RET_VOID);
1181                 RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture2DSize), GL_INVALID_VALUE, RC_RET_VOID);
1182
1183                 Texture2DArray* texture = unit.tex2DArrayBinding ? unit.tex2DArrayBinding : &unit.default2DArrayTex;
1184
1185                 if (texture->isImmutable())
1186                 {
1187                         RC_IF_ERROR(!texture->hasLevel(level), GL_INVALID_OPERATION, RC_RET_VOID);
1188
1189                         ConstPixelBufferAccess dst(texture->getLevel(level));
1190                         RC_IF_ERROR(storageFmt  != dst.getFormat()      ||
1191                                                 width           != dst.getWidth()       ||
1192                                                 height          != dst.getHeight()      ||
1193                                                 depth           != dst.getDepth(), GL_INVALID_OPERATION, RC_RET_VOID);
1194                 }
1195                 else
1196                         texture->allocLevel(level, storageFmt, width, height, depth);
1197
1198                 if (unpackPtr)
1199                 {
1200                         ConstPixelBufferAccess  src             = getUnpack3DAccess(transferFmt, width, height, depth, unpackPtr);
1201                         PixelBufferAccess               dst             (texture->getLevel(level));
1202
1203                         if (isDstFloatDepthFormat)
1204                                 depthValueFloatClampCopy(dst, src);
1205                         else
1206                                 tcu::copy(dst, src);
1207                 }
1208                 else
1209                 {
1210                         // No data supplied, clear to initial
1211                         clearToTextureInitialValue(texture->getLevel(level));
1212                 }
1213         }
1214         else if (target == GL_TEXTURE_3D)
1215         {
1216                 // Validate size and level.
1217                 RC_IF_ERROR(width       > m_limits.maxTexture3DSize ||
1218                                         height  > m_limits.maxTexture3DSize ||
1219                                         depth   > m_limits.maxTexture3DSize, GL_INVALID_VALUE, RC_RET_VOID);
1220                 RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture3DSize), GL_INVALID_VALUE, RC_RET_VOID);
1221
1222                 Texture3D* texture = unit.tex3DBinding ? unit.tex3DBinding : &unit.default3DTex;
1223
1224                 if (texture->isImmutable())
1225                 {
1226                         RC_IF_ERROR(!texture->hasLevel(level), GL_INVALID_OPERATION, RC_RET_VOID);
1227
1228                         ConstPixelBufferAccess dst(texture->getLevel(level));
1229                         RC_IF_ERROR(storageFmt  != dst.getFormat()      ||
1230                                                 width           != dst.getWidth()       ||
1231                                                 height          != dst.getHeight()      ||
1232                                                 depth           != dst.getDepth(), GL_INVALID_OPERATION, RC_RET_VOID);
1233                 }
1234                 else
1235                         texture->allocLevel(level, storageFmt, width, height, depth);
1236
1237                 if (unpackPtr)
1238                 {
1239                         ConstPixelBufferAccess  src             = getUnpack3DAccess(transferFmt, width, height, depth, unpackPtr);
1240                         PixelBufferAccess               dst             (texture->getLevel(level));
1241
1242                         if (isDstFloatDepthFormat)
1243                                 depthValueFloatClampCopy(dst, src);
1244                         else
1245                                 tcu::copy(dst, src);
1246                 }
1247                 else
1248                 {
1249                         // No data supplied, clear to initial
1250                         clearToTextureInitialValue(texture->getLevel(level));
1251                 }
1252         }
1253         else if (target == GL_TEXTURE_CUBE_MAP_ARRAY)
1254         {
1255                 // Validate size and level.
1256                 RC_IF_ERROR(width               != height                                               ||
1257                                         width            > m_limits.maxTexture2DSize    ||
1258                                         depth % 6       != 0                                                    ||
1259                                         depth            > m_limits.maxTexture2DArrayLayers, GL_INVALID_VALUE, RC_RET_VOID);
1260                 RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture2DSize), GL_INVALID_VALUE, RC_RET_VOID);
1261
1262                 TextureCubeArray* texture = unit.texCubeArrayBinding ? unit.texCubeArrayBinding : &unit.defaultCubeArrayTex;
1263
1264                 if (texture->isImmutable())
1265                 {
1266                         RC_IF_ERROR(!texture->hasLevel(level), GL_INVALID_OPERATION, RC_RET_VOID);
1267
1268                         ConstPixelBufferAccess dst(texture->getLevel(level));
1269                         RC_IF_ERROR(storageFmt  != dst.getFormat()      ||
1270                                                 width           != dst.getWidth()       ||
1271                                                 height          != dst.getHeight()      ||
1272                                                 depth           != dst.getDepth(), GL_INVALID_OPERATION, RC_RET_VOID);
1273                 }
1274                 else
1275                         texture->allocLevel(level, storageFmt, width, height, depth);
1276
1277                 if (unpackPtr)
1278                 {
1279                         ConstPixelBufferAccess  src             = getUnpack3DAccess(transferFmt, width, height, depth, unpackPtr);
1280                         PixelBufferAccess               dst             (texture->getLevel(level));
1281
1282                         if (isDstFloatDepthFormat)
1283                                 depthValueFloatClampCopy(dst, src);
1284                         else
1285                                 tcu::copy(dst, src);
1286                 }
1287                 else
1288                 {
1289                         // No data supplied, clear to initial
1290                         clearToTextureInitialValue(texture->getLevel(level));
1291                 }
1292         }
1293         else
1294                 RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1295 }
1296
1297 void ReferenceContext::texSubImage1D (deUint32 target, int level, int xoffset, int width, deUint32 format, deUint32 type, const void* data)
1298 {
1299         texSubImage2D(target, level, xoffset, 0, width, 1, format, type, data);
1300 }
1301
1302 void ReferenceContext::texSubImage2D (deUint32 target, int level, int xoffset, int yoffset, int width, int height, deUint32 format, deUint32 type, const void* data)
1303 {
1304         texSubImage3D(target, level, xoffset, yoffset, 0, width, height, 1, format, type, data);
1305 }
1306
1307 void ReferenceContext::texSubImage3D (deUint32 target, int level, int xoffset, int yoffset, int zoffset, int width, int height, int depth, deUint32 format, deUint32 type, const void* data)
1308 {
1309         TextureUnit& unit = m_textureUnits[m_activeTexture];
1310
1311         RC_IF_ERROR(xoffset < 0 || yoffset < 0 || zoffset < 0,  GL_INVALID_VALUE, RC_RET_VOID);
1312         RC_IF_ERROR(width < 0 || height < 0 || depth < 0,               GL_INVALID_VALUE, RC_RET_VOID);
1313
1314         TextureFormat transferFmt = glu::mapGLTransferFormat(format, type);
1315         RC_IF_ERROR(transferFmt.order   == TextureFormat::CHANNELORDER_LAST ||
1316                                 transferFmt.type        == TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
1317
1318         ConstPixelBufferAccess src = getUnpack3DAccess(transferFmt, width, height, depth, getPixelUnpackPtr(data));
1319
1320         if (target == GL_TEXTURE_1D && glu::isContextTypeGLCore(m_limits.contextType))
1321         {
1322                 Texture1D& texture = unit.tex1DBinding ? *unit.tex1DBinding : unit.default1DTex;
1323
1324                 RC_IF_ERROR(!texture.hasLevel(level), GL_INVALID_VALUE, RC_RET_VOID);
1325
1326                 PixelBufferAccess dst = texture.getLevel(level);
1327
1328                 RC_IF_ERROR(xoffset + width             > dst.getWidth()        ||
1329                                         yoffset + height        > dst.getHeight()       ||
1330                                         zoffset + depth         > dst.getDepth(),
1331                                         GL_INVALID_VALUE, RC_RET_VOID);
1332
1333                 // depth components are limited to [0,1] range
1334                 if (dst.getFormat().order == tcu::TextureFormat::D || dst.getFormat().order == tcu::TextureFormat::DS)
1335                         depthValueFloatClampCopy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1336                 else
1337                         tcu::copy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1338         }
1339         else if (target == GL_TEXTURE_2D)
1340         {
1341                 Texture2D& texture = unit.tex2DBinding ? *unit.tex2DBinding : unit.default2DTex;
1342
1343                 RC_IF_ERROR(!texture.hasLevel(level), GL_INVALID_VALUE, RC_RET_VOID);
1344
1345                 PixelBufferAccess dst = texture.getLevel(level);
1346
1347                 RC_IF_ERROR(xoffset + width             > dst.getWidth()        ||
1348                                         yoffset + height        > dst.getHeight()       ||
1349                                         zoffset + depth         > dst.getDepth(),
1350                                         GL_INVALID_VALUE, RC_RET_VOID);
1351
1352                 // depth components are limited to [0,1] range
1353                 if (dst.getFormat().order == tcu::TextureFormat::D || dst.getFormat().order == tcu::TextureFormat::DS)
1354                         depthValueFloatClampCopy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1355                 else
1356                         tcu::copy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1357         }
1358         else if (target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
1359                          target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
1360                          target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
1361                          target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
1362                          target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z ||
1363                          target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z)
1364         {
1365                 TextureCube&    texture         = unit.texCubeBinding ? *unit.texCubeBinding : unit.defaultCubeTex;
1366                 tcu::CubeFace   face            = mapGLCubeFace(target);
1367
1368                 RC_IF_ERROR(!texture.hasFace(level, face), GL_INVALID_VALUE, RC_RET_VOID);
1369
1370                 PixelBufferAccess dst = texture.getFace(level, face);
1371
1372                 RC_IF_ERROR(xoffset + width             > dst.getWidth()        ||
1373                                         yoffset + height        > dst.getHeight()       ||
1374                                         zoffset + depth         > dst.getDepth(),
1375                                         GL_INVALID_VALUE, RC_RET_VOID);
1376
1377                 // depth components are limited to [0,1] range
1378                 if (dst.getFormat().order == tcu::TextureFormat::D || dst.getFormat().order == tcu::TextureFormat::DS)
1379                         depthValueFloatClampCopy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1380                 else
1381                         tcu::copy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1382         }
1383         else if (target == GL_TEXTURE_3D)
1384         {
1385                 Texture3D& texture = unit.tex3DBinding ? *unit.tex3DBinding : unit.default3DTex;
1386
1387                 RC_IF_ERROR(!texture.hasLevel(level), GL_INVALID_VALUE, RC_RET_VOID);
1388
1389                 PixelBufferAccess dst = texture.getLevel(level);
1390
1391                 RC_IF_ERROR(xoffset + width             > dst.getWidth()        ||
1392                                         yoffset + height        > dst.getHeight()       ||
1393                                         zoffset + depth         > dst.getDepth(),
1394                                         GL_INVALID_VALUE, RC_RET_VOID);
1395
1396                 // depth components are limited to [0,1] range
1397                 if (dst.getFormat().order == tcu::TextureFormat::D || dst.getFormat().order == tcu::TextureFormat::DS)
1398                         depthValueFloatClampCopy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1399                 else
1400                         tcu::copy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1401         }
1402         else if (target == GL_TEXTURE_2D_ARRAY)
1403         {
1404                 Texture2DArray& texture = unit.tex2DArrayBinding ? *unit.tex2DArrayBinding : unit.default2DArrayTex;
1405
1406                 RC_IF_ERROR(!texture.hasLevel(level), GL_INVALID_VALUE, RC_RET_VOID);
1407
1408                 PixelBufferAccess dst = texture.getLevel(level);
1409
1410                 RC_IF_ERROR(xoffset + width             > dst.getWidth()        ||
1411                                         yoffset + height        > dst.getHeight()       ||
1412                                         zoffset + depth         > dst.getDepth(),
1413                                         GL_INVALID_VALUE, RC_RET_VOID);
1414
1415                 // depth components are limited to [0,1] range
1416                 if (dst.getFormat().order == tcu::TextureFormat::D || dst.getFormat().order == tcu::TextureFormat::DS)
1417                         depthValueFloatClampCopy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1418                 else
1419                         tcu::copy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1420         }
1421         else if (target == GL_TEXTURE_CUBE_MAP_ARRAY)
1422         {
1423                 TextureCubeArray& texture = unit.texCubeArrayBinding ? *unit.texCubeArrayBinding : unit.defaultCubeArrayTex;
1424
1425                 RC_IF_ERROR(!texture.hasLevel(level), GL_INVALID_VALUE, RC_RET_VOID);
1426
1427                 PixelBufferAccess dst = texture.getLevel(level);
1428
1429                 RC_IF_ERROR(xoffset + width             > dst.getWidth()        ||
1430                                         yoffset + height        > dst.getHeight()       ||
1431                                         zoffset + depth         > dst.getDepth(),
1432                                         GL_INVALID_VALUE, RC_RET_VOID);
1433
1434                 // depth components are limited to [0,1] range
1435                 if (dst.getFormat().order == tcu::TextureFormat::D || dst.getFormat().order == tcu::TextureFormat::DS)
1436                         depthValueFloatClampCopy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1437                 else
1438                         tcu::copy(tcu::getSubregion(dst, xoffset, yoffset, zoffset, width, height, depth), src);
1439         }
1440         else
1441                 RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1442 }
1443
1444 void ReferenceContext::copyTexImage1D (deUint32 target, int level, deUint32 internalFormat, int x, int y, int width, int border)
1445 {
1446         TextureUnit&                                                    unit            = m_textureUnits[m_activeTexture];
1447         TextureFormat                                                   storageFmt;
1448         rr::MultisampleConstPixelBufferAccess   src                     = getReadColorbuffer();
1449
1450         RC_IF_ERROR(border != 0, GL_INVALID_VALUE, RC_RET_VOID);
1451         RC_IF_ERROR(width < 0 || level < 0, GL_INVALID_VALUE, RC_RET_VOID);
1452         RC_IF_ERROR(isEmpty(src), GL_INVALID_OPERATION, RC_RET_VOID);
1453
1454         // Map storage format.
1455         storageFmt = mapInternalFormat(internalFormat);
1456         RC_IF_ERROR(storageFmt.order    == TextureFormat::CHANNELORDER_LAST ||
1457                                 storageFmt.type         == TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
1458
1459         if (target == GL_TEXTURE_1D)
1460         {
1461                 // Validate size and level.
1462                 RC_IF_ERROR(width > m_limits.maxTexture2DSize, GL_INVALID_VALUE, RC_RET_VOID);
1463                 RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture2DSize), GL_INVALID_VALUE, RC_RET_VOID);
1464
1465                 Texture1D* texture = unit.tex1DBinding ? unit.tex1DBinding : &unit.default1DTex;
1466
1467                 if (texture->isImmutable())
1468                 {
1469                         RC_IF_ERROR(!texture->hasLevel(level), GL_INVALID_OPERATION, RC_RET_VOID);
1470
1471                         ConstPixelBufferAccess dst(texture->getLevel(level));
1472                         RC_IF_ERROR(storageFmt  != dst.getFormat()      ||
1473                                                 width           != dst.getWidth(), GL_INVALID_OPERATION, RC_RET_VOID);
1474                 }
1475                 else
1476                         texture->allocLevel(level, storageFmt, width);
1477
1478                 // Copy from current framebuffer.
1479                 PixelBufferAccess dst = texture->getLevel(level);
1480                 for (int xo = 0; xo < width; xo++)
1481                 {
1482                         if (!de::inBounds(x+xo, 0, src.raw().getHeight()))
1483                                 continue; // Undefined pixel.
1484
1485                         dst.setPixel(rr::resolveMultisamplePixel(src, x+xo, y), xo, 0);
1486                 }
1487         }
1488         else
1489                 RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1490 }
1491
1492 void ReferenceContext::copyTexImage2D (deUint32 target, int level, deUint32 internalFormat, int x, int y, int width, int height, int border)
1493 {
1494         TextureUnit&                                                    unit            = m_textureUnits[m_activeTexture];
1495         TextureFormat                                                   storageFmt;
1496         rr::MultisampleConstPixelBufferAccess   src                     = getReadColorbuffer();
1497
1498         RC_IF_ERROR(border != 0, GL_INVALID_VALUE, RC_RET_VOID);
1499         RC_IF_ERROR(width < 0 || height < 0 || level < 0, GL_INVALID_VALUE, RC_RET_VOID);
1500         RC_IF_ERROR(isEmpty(src), GL_INVALID_OPERATION, RC_RET_VOID);
1501
1502         // Map storage format.
1503         storageFmt = mapInternalFormat(internalFormat);
1504         RC_IF_ERROR(storageFmt.order    == TextureFormat::CHANNELORDER_LAST ||
1505                                 storageFmt.type         == TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
1506
1507         if (target == GL_TEXTURE_2D)
1508         {
1509                 // Validate size and level.
1510                 RC_IF_ERROR(width > m_limits.maxTexture2DSize || height > m_limits.maxTexture2DSize, GL_INVALID_VALUE, RC_RET_VOID);
1511                 RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTexture2DSize), GL_INVALID_VALUE, RC_RET_VOID);
1512
1513                 Texture2D* texture = unit.tex2DBinding ? unit.tex2DBinding : &unit.default2DTex;
1514
1515                 if (texture->isImmutable())
1516                 {
1517                         RC_IF_ERROR(!texture->hasLevel(level), GL_INVALID_OPERATION, RC_RET_VOID);
1518
1519                         ConstPixelBufferAccess dst(texture->getLevel(level));
1520                         RC_IF_ERROR(storageFmt  != dst.getFormat()      ||
1521                                                 width           != dst.getWidth()       ||
1522                                                 height          != dst.getHeight(), GL_INVALID_OPERATION, RC_RET_VOID);
1523                 }
1524                 else
1525                         texture->allocLevel(level, storageFmt, width, height);
1526
1527                 // Copy from current framebuffer.
1528                 PixelBufferAccess dst = texture->getLevel(level);
1529                 for (int yo = 0; yo < height; yo++)
1530                 for (int xo = 0; xo < width; xo++)
1531                 {
1532                         if (!de::inBounds(x+xo, 0, src.raw().getHeight()) || !de::inBounds(y+yo, 0, src.raw().getDepth()))
1533                                 continue; // Undefined pixel.
1534
1535                         dst.setPixel(rr::resolveMultisamplePixel(src, x+xo, y+yo), xo, yo);
1536                 }
1537         }
1538         else if (target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
1539                          target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
1540                          target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
1541                          target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
1542                          target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z ||
1543                          target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z)
1544         {
1545                 // Validate size and level.
1546                 RC_IF_ERROR(width != height || width > m_limits.maxTextureCubeSize, GL_INVALID_VALUE, RC_RET_VOID);
1547                 RC_IF_ERROR(level > deLog2Floor32(m_limits.maxTextureCubeSize), GL_INVALID_VALUE, RC_RET_VOID);
1548
1549                 TextureCube*    texture = unit.texCubeBinding ? unit.texCubeBinding : &unit.defaultCubeTex;
1550                 tcu::CubeFace   face    = mapGLCubeFace(target);
1551
1552                 if (texture->isImmutable())
1553                 {
1554                         RC_IF_ERROR(!texture->hasFace(level, face), GL_INVALID_OPERATION, RC_RET_VOID);
1555
1556                         ConstPixelBufferAccess dst(texture->getFace(level, face));
1557                         RC_IF_ERROR(storageFmt  != dst.getFormat()      ||
1558                                                 width           != dst.getWidth()       ||
1559                                                 height          != dst.getHeight(), GL_INVALID_OPERATION, RC_RET_VOID);
1560                 }
1561                 else
1562                         texture->allocFace(level, face, storageFmt, width, height);
1563
1564                 // Copy from current framebuffer.
1565                 PixelBufferAccess dst = texture->getFace(level, face);
1566                 for (int yo = 0; yo < height; yo++)
1567                 for (int xo = 0; xo < width; xo++)
1568                 {
1569                         if (!de::inBounds(x+xo, 0, src.raw().getHeight()) || !de::inBounds(y+yo, 0, src.raw().getDepth()))
1570                                 continue; // Undefined pixel.
1571
1572                         dst.setPixel(rr::resolveMultisamplePixel(src, x+xo, y+yo), xo, yo);
1573                 }
1574         }
1575         else
1576                 RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1577 }
1578
1579 void ReferenceContext::copyTexSubImage1D (deUint32 target, int level, int xoffset, int x, int y, int width)
1580 {
1581         TextureUnit&                                                    unit    = m_textureUnits[m_activeTexture];
1582         rr::MultisampleConstPixelBufferAccess   src             = getReadColorbuffer();
1583
1584         RC_IF_ERROR(xoffset < 0,        GL_INVALID_VALUE,               RC_RET_VOID);
1585         RC_IF_ERROR(width < 0,          GL_INVALID_VALUE,               RC_RET_VOID);
1586         RC_IF_ERROR(isEmpty(src),       GL_INVALID_OPERATION,   RC_RET_VOID);
1587
1588         if (target == GL_TEXTURE_1D)
1589         {
1590                 Texture1D& texture = unit.tex1DBinding ? *unit.tex1DBinding : unit.default1DTex;
1591
1592                 RC_IF_ERROR(!texture.hasLevel(level), GL_INVALID_VALUE, RC_RET_VOID);
1593
1594                 PixelBufferAccess dst = texture.getLevel(level);
1595
1596                 RC_IF_ERROR(xoffset + width > dst.getWidth(), GL_INVALID_VALUE, RC_RET_VOID);
1597
1598                 for (int xo = 0; xo < width; xo++)
1599                 {
1600                         if (!de::inBounds(x+xo, 0, src.raw().getHeight()))
1601                                 continue;
1602
1603                         dst.setPixel(rr::resolveMultisamplePixel(src, x+xo, y), xo+xoffset, 0);
1604                 }
1605         }
1606         else
1607                 RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1608 }
1609
1610 void ReferenceContext::copyTexSubImage2D (deUint32 target, int level, int xoffset, int yoffset, int x, int y, int width, int height)
1611 {
1612         TextureUnit&                                                    unit    = m_textureUnits[m_activeTexture];
1613         rr::MultisampleConstPixelBufferAccess   src             = getReadColorbuffer();
1614
1615         RC_IF_ERROR(xoffset < 0 || yoffset < 0,                                 GL_INVALID_VALUE, RC_RET_VOID);
1616         RC_IF_ERROR(width < 0 || height < 0,                                    GL_INVALID_VALUE, RC_RET_VOID);
1617         RC_IF_ERROR(isEmpty(src),                                                               GL_INVALID_OPERATION, RC_RET_VOID);
1618
1619         if (target == GL_TEXTURE_2D)
1620         {
1621                 Texture2D& texture = unit.tex2DBinding ? *unit.tex2DBinding : unit.default2DTex;
1622
1623                 RC_IF_ERROR(!texture.hasLevel(level), GL_INVALID_VALUE, RC_RET_VOID);
1624
1625                 PixelBufferAccess dst = texture.getLevel(level);
1626
1627                 RC_IF_ERROR(xoffset + width             > dst.getWidth() ||
1628                                         yoffset + height        > dst.getHeight(),
1629                                         GL_INVALID_VALUE, RC_RET_VOID);
1630
1631                 for (int yo = 0; yo < height; yo++)
1632                 for (int xo = 0; xo < width; xo++)
1633                 {
1634                         if (!de::inBounds(x+xo, 0, src.raw().getHeight()) || !de::inBounds(y+yo, 0, src.raw().getDepth()))
1635                                 continue;
1636
1637                         dst.setPixel(rr::resolveMultisamplePixel(src, x+xo, y+yo), xo+xoffset, yo+yoffset);
1638                 }
1639         }
1640         else if (target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
1641                          target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
1642                          target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
1643                          target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
1644                          target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z ||
1645                          target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z)
1646         {
1647                 TextureCube&    texture         = unit.texCubeBinding ? *unit.texCubeBinding : unit.defaultCubeTex;
1648                 tcu::CubeFace   face            = mapGLCubeFace(target);
1649
1650                 RC_IF_ERROR(!texture.hasFace(level, face), GL_INVALID_VALUE, RC_RET_VOID);
1651
1652                 PixelBufferAccess dst = texture.getFace(level, face);
1653
1654                 RC_IF_ERROR(xoffset + width             > dst.getWidth() ||
1655                                         yoffset + height        > dst.getHeight(),
1656                                         GL_INVALID_VALUE, RC_RET_VOID);
1657
1658                 for (int yo = 0; yo < height; yo++)
1659                 for (int xo = 0; xo < width; xo++)
1660                 {
1661                         if (!de::inBounds(x+xo, 0, src.raw().getHeight()) || !de::inBounds(y+yo, 0, src.raw().getDepth()))
1662                                 continue;
1663
1664                         dst.setPixel(rr::resolveMultisamplePixel(src, x+xo, y+yo), xo+xoffset, yo+yoffset);
1665                 }
1666         }
1667         else
1668                 RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1669 }
1670
1671 void ReferenceContext::copyTexSubImage3D (deUint32 target, int level, int xoffset, int yoffset, int zoffset, int x, int y, int width, int height)
1672 {
1673         DE_UNREF(target && level && xoffset && yoffset && zoffset && x && y && width && height);
1674         DE_ASSERT(false);
1675 }
1676
1677 void ReferenceContext::texStorage2D (deUint32 target, int levels, deUint32 internalFormat, int width, int height)
1678 {
1679         TextureUnit&            unit            = m_textureUnits[m_activeTexture];
1680         TextureFormat           storageFmt;
1681
1682         RC_IF_ERROR(width <= 0 || height <= 0, GL_INVALID_VALUE, RC_RET_VOID);
1683         RC_IF_ERROR(!de::inRange(levels, 1, (int)deLog2Floor32(de::max(width, height))+1), GL_INVALID_VALUE, RC_RET_VOID);
1684
1685         // Map storage format.
1686         storageFmt = mapInternalFormat(internalFormat);
1687         RC_IF_ERROR(storageFmt.order    == TextureFormat::CHANNELORDER_LAST ||
1688                                 storageFmt.type         == TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
1689
1690         if (target == GL_TEXTURE_2D)
1691         {
1692                 Texture2D& texture = unit.tex2DBinding ? *unit.tex2DBinding : unit.default2DTex;
1693
1694                 RC_IF_ERROR(width > m_limits.maxTexture2DSize || height >= m_limits.maxTexture2DSize, GL_INVALID_VALUE, RC_RET_VOID);
1695                 RC_IF_ERROR(texture.isImmutable(), GL_INVALID_OPERATION, RC_RET_VOID);
1696
1697                 texture.clearLevels();
1698                 texture.setImmutable();
1699
1700                 for (int level = 0; level < levels; level++)
1701                 {
1702                         int levelW = de::max(1, width >> level);
1703                         int levelH = de::max(1, height >> level);
1704
1705                         texture.allocLevel(level, storageFmt, levelW, levelH);
1706                 }
1707         }
1708         else if (target == GL_TEXTURE_CUBE_MAP)
1709         {
1710                 TextureCube& texture = unit.texCubeBinding ? *unit.texCubeBinding : unit.defaultCubeTex;
1711
1712                 RC_IF_ERROR(width > m_limits.maxTextureCubeSize || height > m_limits.maxTextureCubeSize, GL_INVALID_VALUE, RC_RET_VOID);
1713                 RC_IF_ERROR(texture.isImmutable(), GL_INVALID_OPERATION, RC_RET_VOID);
1714
1715                 texture.clearLevels();
1716                 texture.setImmutable();
1717
1718                 for (int level = 0; level < levels; level++)
1719                 {
1720                         int levelW = de::max(1, width >> level);
1721                         int levelH = de::max(1, height >> level);
1722
1723                         for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
1724                                 texture.allocFace(level, (tcu::CubeFace)face, storageFmt, levelW, levelH);
1725                 }
1726         }
1727         else
1728                 RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1729 }
1730
1731 void ReferenceContext::texStorage3D (deUint32 target, int levels, deUint32 internalFormat, int width, int height, int depth)
1732 {
1733         TextureUnit&            unit            = m_textureUnits[m_activeTexture];
1734         TextureFormat           storageFmt;
1735
1736         RC_IF_ERROR(width <= 0 || height <= 0, GL_INVALID_VALUE, RC_RET_VOID);
1737         RC_IF_ERROR(!de::inRange(levels, 1, (int)deLog2Floor32(de::max(width, height))+1), GL_INVALID_VALUE, RC_RET_VOID);
1738
1739         // Map storage format.
1740         storageFmt = mapInternalFormat(internalFormat);
1741         RC_IF_ERROR(storageFmt.order    == TextureFormat::CHANNELORDER_LAST ||
1742                                 storageFmt.type         == TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
1743
1744         if (target == GL_TEXTURE_2D_ARRAY)
1745         {
1746                 Texture2DArray& texture = unit.tex2DArrayBinding ? *unit.tex2DArrayBinding : unit.default2DArrayTex;
1747
1748                 RC_IF_ERROR(width       >       m_limits.maxTexture2DSize       ||
1749                                         height  >=      m_limits.maxTexture2DSize       ||
1750                                         depth   >=      m_limits.maxTexture2DArrayLayers, GL_INVALID_VALUE, RC_RET_VOID);
1751                 RC_IF_ERROR(texture.isImmutable(), GL_INVALID_OPERATION, RC_RET_VOID);
1752
1753                 texture.clearLevels();
1754                 texture.setImmutable();
1755
1756                 for (int level = 0; level < levels; level++)
1757                 {
1758                         int levelW = de::max(1, width >> level);
1759                         int levelH = de::max(1, height >> level);
1760
1761                         texture.allocLevel(level, storageFmt, levelW, levelH, depth);
1762                 }
1763         }
1764         else if (target == GL_TEXTURE_3D)
1765         {
1766                 Texture3D& texture = unit.tex3DBinding ? *unit.tex3DBinding : unit.default3DTex;
1767
1768                 RC_IF_ERROR(width       > m_limits.maxTexture3DSize     ||
1769                                         height  > m_limits.maxTexture3DSize     ||
1770                                         depth   > m_limits.maxTexture3DSize, GL_INVALID_VALUE, RC_RET_VOID);
1771                 RC_IF_ERROR(texture.isImmutable(), GL_INVALID_OPERATION, RC_RET_VOID);
1772
1773                 texture.clearLevels();
1774                 texture.setImmutable();
1775
1776                 for (int level = 0; level < levels; level++)
1777                 {
1778                         int levelW = de::max(1, width           >> level);
1779                         int levelH = de::max(1, height  >> level);
1780                         int levelD = de::max(1, depth           >> level);
1781
1782                         texture.allocLevel(level, storageFmt, levelW, levelH, levelD);
1783                 }
1784         }
1785         else if (target == GL_TEXTURE_CUBE_MAP_ARRAY)
1786         {
1787                 TextureCubeArray& texture = unit.texCubeArrayBinding ? *unit.texCubeArrayBinding : unit.defaultCubeArrayTex;
1788
1789                 RC_IF_ERROR(width               !=      height                                                          ||
1790                                         depth % 6       != 0                                                                    ||
1791                                         width           >       m_limits.maxTexture2DSize                       ||
1792                                         depth           >=      m_limits.maxTexture2DArrayLayers, GL_INVALID_VALUE, RC_RET_VOID);
1793                 RC_IF_ERROR(texture.isImmutable(), GL_INVALID_OPERATION, RC_RET_VOID);
1794
1795                 texture.clearLevels();
1796                 texture.setImmutable();
1797
1798                 for (int level = 0; level < levels; level++)
1799                 {
1800                         int levelW = de::max(1, width >> level);
1801                         int levelH = de::max(1, height >> level);
1802
1803                         texture.allocLevel(level, storageFmt, levelW, levelH, depth);
1804                 }
1805         }
1806         else
1807                 RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1808 }
1809
1810 // \todo [2014-02-19 pyry] Duplicated with code in gluTextureUtil.hpp
1811
1812 static inline tcu::Sampler::WrapMode mapGLWrapMode (int value)
1813 {
1814         switch (value)
1815         {
1816                 case GL_CLAMP_TO_EDGE:          return tcu::Sampler::CLAMP_TO_EDGE;
1817                 case GL_REPEAT:                         return tcu::Sampler::REPEAT_GL;
1818                 case GL_MIRRORED_REPEAT:        return tcu::Sampler::MIRRORED_REPEAT_GL;
1819                 default:                                        return tcu::Sampler::WRAPMODE_LAST;
1820         }
1821 }
1822
1823 static inline tcu::Sampler::FilterMode mapGLFilterMode (int value)
1824 {
1825         switch (value)
1826         {
1827                 case GL_NEAREST:                                return tcu::Sampler::NEAREST;
1828                 case GL_LINEAR:                                 return tcu::Sampler::LINEAR;
1829                 case GL_NEAREST_MIPMAP_NEAREST: return tcu::Sampler::NEAREST_MIPMAP_NEAREST;
1830                 case GL_NEAREST_MIPMAP_LINEAR:  return tcu::Sampler::NEAREST_MIPMAP_LINEAR;
1831                 case GL_LINEAR_MIPMAP_NEAREST:  return tcu::Sampler::LINEAR_MIPMAP_NEAREST;
1832                 case GL_LINEAR_MIPMAP_LINEAR:   return tcu::Sampler::LINEAR_MIPMAP_LINEAR;
1833                 default:                                                return tcu::Sampler::FILTERMODE_LAST;
1834         }
1835 }
1836
1837 void ReferenceContext::texParameteri (deUint32 target, deUint32 pname, int value)
1838 {
1839         TextureUnit&    unit            = m_textureUnits[m_activeTexture];
1840         Texture*                texture         = DE_NULL;
1841
1842         switch (target)
1843         {
1844                 case GL_TEXTURE_1D:                             texture = unit.tex1DBinding                     ? unit.tex1DBinding                     : &unit.default1DTex;                   break;
1845                 case GL_TEXTURE_2D:                             texture = unit.tex2DBinding                     ? unit.tex2DBinding                     : &unit.default2DTex;                   break;
1846                 case GL_TEXTURE_CUBE_MAP:               texture = unit.texCubeBinding           ? unit.texCubeBinding           : &unit.defaultCubeTex;                 break;
1847                 case GL_TEXTURE_2D_ARRAY:               texture = unit.tex2DArrayBinding        ? unit.tex2DArrayBinding        : &unit.default2DArrayTex;              break;
1848                 case GL_TEXTURE_3D:                             texture = unit.tex3DBinding                     ? unit.tex3DBinding                     : &unit.default3DTex;                   break;
1849                 case GL_TEXTURE_CUBE_MAP_ARRAY: texture = unit.texCubeArrayBinding      ? unit.texCubeArrayBinding      : &unit.defaultCubeArrayTex;    break;
1850
1851                 default:                                        RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1852         }
1853
1854         switch (pname)
1855         {
1856                 case GL_TEXTURE_WRAP_S:
1857                 {
1858                         tcu::Sampler::WrapMode wrapS = mapGLWrapMode(value);
1859                         RC_IF_ERROR(wrapS == tcu::Sampler::WRAPMODE_LAST, GL_INVALID_VALUE, RC_RET_VOID);
1860                         texture->getSampler().wrapS = wrapS;
1861                         break;
1862                 }
1863
1864                 case GL_TEXTURE_WRAP_T:
1865                 {
1866                         tcu::Sampler::WrapMode wrapT = mapGLWrapMode(value);
1867                         RC_IF_ERROR(wrapT == tcu::Sampler::WRAPMODE_LAST, GL_INVALID_VALUE, RC_RET_VOID);
1868                         texture->getSampler().wrapT = wrapT;
1869                         break;
1870                 }
1871
1872                 case GL_TEXTURE_WRAP_R:
1873                 {
1874                         tcu::Sampler::WrapMode wrapR = mapGLWrapMode(value);
1875                         RC_IF_ERROR(wrapR == tcu::Sampler::WRAPMODE_LAST, GL_INVALID_VALUE, RC_RET_VOID);
1876                         texture->getSampler().wrapR = wrapR;
1877                         break;
1878                 }
1879
1880                 case GL_TEXTURE_MIN_FILTER:
1881                 {
1882                         tcu::Sampler::FilterMode minMode = mapGLFilterMode(value);
1883                         RC_IF_ERROR(minMode == tcu::Sampler::FILTERMODE_LAST, GL_INVALID_VALUE, RC_RET_VOID);
1884                         texture->getSampler().minFilter = minMode;
1885                         break;
1886                 }
1887
1888                 case GL_TEXTURE_MAG_FILTER:
1889                 {
1890                         tcu::Sampler::FilterMode magMode = mapGLFilterMode(value);
1891                         RC_IF_ERROR(magMode != tcu::Sampler::LINEAR && magMode != tcu::Sampler::NEAREST,
1892                                                 GL_INVALID_VALUE, RC_RET_VOID);
1893                         texture->getSampler().magFilter = magMode;
1894                         break;
1895                 }
1896
1897                 case GL_TEXTURE_MAX_LEVEL:
1898                 {
1899                         RC_IF_ERROR(value < 0, GL_INVALID_VALUE, RC_RET_VOID);
1900                         texture->setMaxLevel(value);
1901                         break;
1902                 }
1903
1904                 default:
1905                         RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
1906         }
1907 }
1908
1909 static inline Framebuffer::AttachmentPoint mapGLAttachmentPoint (deUint32 attachment)
1910 {
1911         switch (attachment)
1912         {
1913                 case GL_COLOR_ATTACHMENT0:      return Framebuffer::ATTACHMENTPOINT_COLOR0;
1914                 case GL_DEPTH_ATTACHMENT:       return Framebuffer::ATTACHMENTPOINT_DEPTH;
1915                 case GL_STENCIL_ATTACHMENT:     return Framebuffer::ATTACHMENTPOINT_STENCIL;
1916                 default:                                        return Framebuffer::ATTACHMENTPOINT_LAST;
1917         }
1918 }
1919
1920 static inline Framebuffer::TexTarget mapGLFboTexTarget (deUint32 target)
1921 {
1922         switch (target)
1923         {
1924                 case GL_TEXTURE_2D:                                             return Framebuffer::TEXTARGET_2D;
1925                 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:    return Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_X;
1926                 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:    return Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_Y;
1927                 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:    return Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_Z;
1928                 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:    return Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_X;
1929                 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:    return Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_Y;
1930                 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:    return Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_Z;
1931                 default:                                                                return Framebuffer::TEXTARGET_LAST;
1932         }
1933 }
1934
1935 void ReferenceContext::acquireFboAttachmentReference (const Framebuffer::Attachment& attachment)
1936 {
1937         switch (attachment.type)
1938         {
1939                 case Framebuffer::ATTACHMENTTYPE_TEXTURE:
1940                 {
1941                         TCU_CHECK(attachment.name != 0);
1942                         Texture* texture = m_textures.find(attachment.name);
1943                         TCU_CHECK(texture);
1944                         m_textures.acquireReference(texture);
1945                         break;
1946                 }
1947
1948                 case Framebuffer::ATTACHMENTTYPE_RENDERBUFFER:
1949                 {
1950                         TCU_CHECK(attachment.name != 0);
1951                         Renderbuffer* rbo = m_renderbuffers.find(attachment.name);
1952                         TCU_CHECK(rbo);
1953                         m_renderbuffers.acquireReference(rbo);
1954                         break;
1955                 }
1956
1957                 default:
1958                         break; // Silently ignore
1959         }
1960 }
1961
1962 void ReferenceContext::releaseFboAttachmentReference (const Framebuffer::Attachment& attachment)
1963 {
1964         switch (attachment.type)
1965         {
1966                 case Framebuffer::ATTACHMENTTYPE_TEXTURE:
1967                 {
1968                         TCU_CHECK(attachment.name != 0);
1969                         Texture* texture = m_textures.find(attachment.name);
1970                         TCU_CHECK(texture);
1971                         m_textures.releaseReference(texture);
1972                         break;
1973                 }
1974
1975                 case Framebuffer::ATTACHMENTTYPE_RENDERBUFFER:
1976                 {
1977                         TCU_CHECK(attachment.name != 0);
1978                         Renderbuffer* rbo = m_renderbuffers.find(attachment.name);
1979                         TCU_CHECK(rbo);
1980                         m_renderbuffers.releaseReference(rbo);
1981                         break;
1982                 }
1983
1984                 default:
1985                         break; // Silently ignore
1986         }
1987 }
1988
1989 void ReferenceContext::framebufferTexture2D (deUint32 target, deUint32 attachment, deUint32 textarget, deUint32 texture, int level)
1990 {
1991         if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
1992         {
1993                 // Attach to both depth and stencil.
1994                 framebufferTexture2D(target, GL_DEPTH_ATTACHMENT,       textarget, texture, level);
1995                 framebufferTexture2D(target, GL_STENCIL_ATTACHMENT,     textarget, texture, level);
1996         }
1997         else
1998         {
1999                 Framebuffer::AttachmentPoint    point                   = mapGLAttachmentPoint(attachment);
2000                 Texture*                                                texObj                  = DE_NULL;
2001                 Framebuffer::TexTarget                  fboTexTarget    = mapGLFboTexTarget(textarget);
2002
2003                 RC_IF_ERROR(target != GL_FRAMEBUFFER            &&
2004                                         target != GL_DRAW_FRAMEBUFFER   &&
2005                                         target != GL_READ_FRAMEBUFFER,                          GL_INVALID_ENUM,                RC_RET_VOID);
2006                 RC_IF_ERROR(point == Framebuffer::ATTACHMENTPOINT_LAST, GL_INVALID_ENUM,                RC_RET_VOID);
2007
2008                 // Select binding point.
2009                 rc::Framebuffer* framebufferBinding = (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER) ? m_drawFramebufferBinding : m_readFramebufferBinding;
2010                 RC_IF_ERROR(!framebufferBinding, GL_INVALID_OPERATION, RC_RET_VOID);
2011
2012                 // If framebuffer object is bound for both reading and writing then we need to acquire/release multiple references.
2013                 int bindingRefCount = (framebufferBinding == m_drawFramebufferBinding ? 1 : 0)
2014                                                         + (framebufferBinding == m_readFramebufferBinding ? 1 : 0);
2015
2016                 if (texture != 0)
2017                 {
2018                         texObj = m_textures.find(texture);
2019
2020                         RC_IF_ERROR(!texObj,            GL_INVALID_OPERATION,   RC_RET_VOID);
2021                         RC_IF_ERROR(level != 0,         GL_INVALID_VALUE,               RC_RET_VOID); // \todo [2012-03-19 pyry] We should allow other levels as well.
2022
2023                         if (texObj->getType() == Texture::TYPE_2D)
2024                                 RC_IF_ERROR(fboTexTarget != Framebuffer::TEXTARGET_2D, GL_INVALID_OPERATION, RC_RET_VOID);
2025                         else
2026                         {
2027                                 TCU_CHECK(texObj->getType() == Texture::TYPE_CUBE_MAP);
2028                                 if (!deInRange32(fboTexTarget, Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_X, Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_Z))
2029                                         RC_ERROR_RET(GL_INVALID_OPERATION, RC_RET_VOID);
2030                         }
2031                 }
2032
2033                 Framebuffer::Attachment& fboAttachment = framebufferBinding->getAttachment(point);
2034                 for (int ndx = 0; ndx < bindingRefCount; ndx++)
2035                         releaseFboAttachmentReference(fboAttachment);
2036                 fboAttachment = Framebuffer::Attachment();
2037
2038                 if (texObj)
2039                 {
2040                         fboAttachment.type                      = Framebuffer::ATTACHMENTTYPE_TEXTURE;
2041                         fboAttachment.name                      = texObj->getName();
2042                         fboAttachment.texTarget         = fboTexTarget;
2043                         fboAttachment.level                     = level;
2044
2045                         for (int ndx = 0; ndx < bindingRefCount; ndx++)
2046                                 acquireFboAttachmentReference(fboAttachment);
2047                 }
2048         }
2049 }
2050
2051 void ReferenceContext::framebufferTextureLayer (deUint32 target, deUint32 attachment, deUint32 texture, int level, int layer)
2052 {
2053         if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
2054         {
2055                 // Attach to both depth and stencil.
2056                 framebufferTextureLayer(target, GL_DEPTH_ATTACHMENT,    texture, level, layer);
2057                 framebufferTextureLayer(target, GL_STENCIL_ATTACHMENT,  texture, level, layer);
2058         }
2059         else
2060         {
2061                 Framebuffer::AttachmentPoint    point                   = mapGLAttachmentPoint(attachment);
2062                 Texture*                                                texObj                  = DE_NULL;
2063
2064                 RC_IF_ERROR(target != GL_FRAMEBUFFER            &&
2065                                         target != GL_DRAW_FRAMEBUFFER   &&
2066                                         target != GL_READ_FRAMEBUFFER,                          GL_INVALID_ENUM,                RC_RET_VOID);
2067                 RC_IF_ERROR(point == Framebuffer::ATTACHMENTPOINT_LAST, GL_INVALID_ENUM,                RC_RET_VOID);
2068
2069                 // Select binding point.
2070                 rc::Framebuffer* framebufferBinding = (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER) ? m_drawFramebufferBinding : m_readFramebufferBinding;
2071                 RC_IF_ERROR(!framebufferBinding, GL_INVALID_OPERATION, RC_RET_VOID);
2072
2073                 // If framebuffer object is bound for both reading and writing then we need to acquire/release multiple references.
2074                 int bindingRefCount = (framebufferBinding == m_drawFramebufferBinding ? 1 : 0)
2075                                                         + (framebufferBinding == m_readFramebufferBinding ? 1 : 0);
2076
2077                 if (texture != 0)
2078                 {
2079                         texObj = m_textures.find(texture);
2080
2081                         RC_IF_ERROR(!texObj,            GL_INVALID_OPERATION,   RC_RET_VOID);
2082                         RC_IF_ERROR(level != 0,         GL_INVALID_VALUE,               RC_RET_VOID); // \todo [2012-03-19 pyry] We should allow other levels as well.
2083
2084                         RC_IF_ERROR(texObj->getType() != Texture::TYPE_2D_ARRAY                 &&
2085                                                 texObj->getType() != Texture::TYPE_3D                           &&
2086                                                 texObj->getType() != Texture::TYPE_CUBE_MAP_ARRAY,                              GL_INVALID_OPERATION,   RC_RET_VOID);
2087
2088                         if (texObj->getType() == Texture::TYPE_2D_ARRAY || texObj->getType() == Texture::TYPE_CUBE_MAP_ARRAY)
2089                         {
2090                                 RC_IF_ERROR((layer < 0) || (layer >= GL_MAX_ARRAY_TEXTURE_LAYERS),              GL_INVALID_VALUE,               RC_RET_VOID);
2091                                 RC_IF_ERROR((level < 0) || (level > deLog2Floor32(GL_MAX_TEXTURE_SIZE)),GL_INVALID_VALUE,               RC_RET_VOID);
2092                         }
2093                         else if (texObj->getType() == Texture::TYPE_3D)
2094                         {
2095                                 RC_IF_ERROR((layer < 0) || (layer >= GL_MAX_3D_TEXTURE_SIZE),                           GL_INVALID_VALUE,               RC_RET_VOID);
2096                                 RC_IF_ERROR((level < 0) || (level > deLog2Floor32(GL_MAX_3D_TEXTURE_SIZE)),     GL_INVALID_VALUE,               RC_RET_VOID);
2097                         }
2098                 }
2099
2100                 Framebuffer::Attachment& fboAttachment = framebufferBinding->getAttachment(point);
2101                 for (int ndx = 0; ndx < bindingRefCount; ndx++)
2102                         releaseFboAttachmentReference(fboAttachment);
2103                 fboAttachment = Framebuffer::Attachment();
2104
2105                 if (texObj)
2106                 {
2107                         fboAttachment.type                      = Framebuffer::ATTACHMENTTYPE_TEXTURE;
2108                         fboAttachment.name                      = texObj->getName();
2109                         fboAttachment.texTarget         = texLayeredTypeToTarget(texObj->getType());
2110                         fboAttachment.level                     = level;
2111                         fboAttachment.layer                     = layer;
2112
2113                         DE_ASSERT(fboAttachment.texTarget != Framebuffer::TEXTARGET_LAST);
2114
2115                         for (int ndx = 0; ndx < bindingRefCount; ndx++)
2116                                 acquireFboAttachmentReference(fboAttachment);
2117                 }
2118         }
2119 }
2120
2121 void ReferenceContext::framebufferRenderbuffer (deUint32 target, deUint32 attachment, deUint32 renderbuffertarget, deUint32 renderbuffer)
2122 {
2123         if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
2124         {
2125                 // Attach both to depth and stencil.
2126                 framebufferRenderbuffer(target, GL_DEPTH_ATTACHMENT,    renderbuffertarget, renderbuffer);
2127                 framebufferRenderbuffer(target, GL_STENCIL_ATTACHMENT,  renderbuffertarget, renderbuffer);
2128         }
2129         else
2130         {
2131                 Framebuffer::AttachmentPoint    point                   = mapGLAttachmentPoint(attachment);
2132                 Renderbuffer*                                   rbo                             = DE_NULL;
2133
2134                 RC_IF_ERROR(target != GL_FRAMEBUFFER            &&
2135                                         target != GL_DRAW_FRAMEBUFFER   &&
2136                                         target != GL_READ_FRAMEBUFFER,                          GL_INVALID_ENUM,                RC_RET_VOID);
2137                 RC_IF_ERROR(point == Framebuffer::ATTACHMENTPOINT_LAST, GL_INVALID_ENUM,                RC_RET_VOID);
2138
2139                 // Select binding point.
2140                 rc::Framebuffer* framebufferBinding = (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER) ? m_drawFramebufferBinding : m_readFramebufferBinding;
2141                 RC_IF_ERROR(!framebufferBinding, GL_INVALID_OPERATION, RC_RET_VOID);
2142
2143                 // If framebuffer object is bound for both reading and writing then we need to acquire/release multiple references.
2144                 int bindingRefCount = (framebufferBinding == m_drawFramebufferBinding ? 1 : 0)
2145                                                         + (framebufferBinding == m_readFramebufferBinding ? 1 : 0);
2146
2147                 if (renderbuffer != 0)
2148                 {
2149                         rbo = m_renderbuffers.find(renderbuffer);
2150
2151                         RC_IF_ERROR(renderbuffertarget != GL_RENDERBUFFER,      GL_INVALID_ENUM,                RC_RET_VOID);
2152                         RC_IF_ERROR(!rbo,                                                                       GL_INVALID_OPERATION,   RC_RET_VOID);
2153                 }
2154
2155                 Framebuffer::Attachment& fboAttachment = framebufferBinding->getAttachment(point);
2156                 for (int ndx = 0; ndx < bindingRefCount; ndx++)
2157                         releaseFboAttachmentReference(fboAttachment);
2158                 fboAttachment = Framebuffer::Attachment();
2159
2160                 if (rbo)
2161                 {
2162                         fboAttachment.type      = Framebuffer::ATTACHMENTTYPE_RENDERBUFFER;
2163                         fboAttachment.name      = rbo->getName();
2164
2165                         for (int ndx = 0; ndx < bindingRefCount; ndx++)
2166                                 acquireFboAttachmentReference(fboAttachment);
2167                 }
2168         }
2169 }
2170
2171 deUint32 ReferenceContext::checkFramebufferStatus (deUint32 target)
2172 {
2173         RC_IF_ERROR(target != GL_FRAMEBUFFER            &&
2174                                 target != GL_DRAW_FRAMEBUFFER   &&
2175                                 target != GL_READ_FRAMEBUFFER, GL_INVALID_ENUM, 0);
2176
2177         // Select binding point.
2178         rc::Framebuffer* framebufferBinding = (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER) ? m_drawFramebufferBinding : m_readFramebufferBinding;
2179
2180         // Default framebuffer is always complete.
2181         if (!framebufferBinding)
2182                 return GL_FRAMEBUFFER_COMPLETE;
2183
2184         int             width                           = -1;
2185         int             height                          = -1;
2186         bool    hasAttachment           = false;
2187         bool    attachmentComplete      = true;
2188         bool    dimensionsOk            = true;
2189
2190         for (int point = 0; point < Framebuffer::ATTACHMENTPOINT_LAST; point++)
2191         {
2192                 const Framebuffer::Attachment&  attachment                      = framebufferBinding->getAttachment((Framebuffer::AttachmentPoint)point);
2193                 int                                                             attachmentWidth         = 0;
2194                 int                                                             attachmentHeight        = 0;
2195                 tcu::TextureFormat                              attachmentFormat;
2196
2197                 if (attachment.type == Framebuffer::ATTACHMENTTYPE_TEXTURE)
2198                 {
2199                         const Texture*                                  texture = m_textures.find(attachment.name);
2200                         tcu::ConstPixelBufferAccess             level;
2201                         TCU_CHECK(texture);
2202
2203                         if (attachment.texTarget == Framebuffer::TEXTARGET_2D)
2204                         {
2205                                 DE_ASSERT(texture->getType() == Texture::TYPE_2D);
2206                                 const Texture2D* tex2D = static_cast<const Texture2D*>(texture);
2207
2208                                 if (tex2D->hasLevel(attachment.level))
2209                                         level = tex2D->getLevel(attachment.level);
2210                         }
2211                         else if (deInRange32(attachment.texTarget, Framebuffer::TEXTARGET_CUBE_MAP_POSITIVE_X,
2212                                                                                                            Framebuffer::TEXTARGET_CUBE_MAP_NEGATIVE_Z))
2213                         {
2214                                 DE_ASSERT(texture->getType() == Texture::TYPE_CUBE_MAP);
2215
2216                                 const TextureCube*      texCube = static_cast<const TextureCube*>(texture);
2217                                 const tcu::CubeFace     face    = texTargetToFace(attachment.texTarget);
2218                                 TCU_CHECK(de::inBounds<int>(face, 0, tcu::CUBEFACE_LAST));
2219
2220                                 if (texCube->hasFace(attachment.level, face))
2221                                         level = texCube->getFace(attachment.level, face);
2222                         }
2223                         else if (attachment.texTarget == Framebuffer::TEXTARGET_2D_ARRAY)
2224                         {
2225                                 DE_ASSERT(texture->getType() == Texture::TYPE_2D_ARRAY);
2226                                 const Texture2DArray* tex2DArr = static_cast<const Texture2DArray*>(texture);
2227
2228                                 if (tex2DArr->hasLevel(attachment.level))
2229                                         level = tex2DArr->getLevel(attachment.level); // \note Slice doesn't matter here.
2230                         }
2231                         else if (attachment.texTarget == Framebuffer::TEXTARGET_3D)
2232                         {
2233                                 DE_ASSERT(texture->getType() == Texture::TYPE_3D);
2234                                 const Texture3D* tex3D = static_cast<const Texture3D*>(texture);
2235
2236                                 if (tex3D->hasLevel(attachment.level))
2237                                         level = tex3D->getLevel(attachment.level); // \note Slice doesn't matter here.
2238                         }
2239                         else if (attachment.texTarget == Framebuffer::TEXTARGET_CUBE_MAP_ARRAY)
2240                         {
2241                                 DE_ASSERT(texture->getType() == Texture::TYPE_CUBE_MAP_ARRAY);
2242                                 const TextureCubeArray* texCubeArr = static_cast<const TextureCubeArray*>(texture);
2243
2244                                 if (texCubeArr->hasLevel(attachment.level))
2245                                         level = texCubeArr->getLevel(attachment.level); // \note Slice doesn't matter here.
2246                         }
2247                         else
2248                                 TCU_FAIL("Framebuffer attached to a texture but no valid target specified");
2249
2250                         attachmentWidth         = level.getWidth();
2251                         attachmentHeight        = level.getHeight();
2252                         attachmentFormat        = level.getFormat();
2253                 }
2254                 else if (attachment.type == Framebuffer::ATTACHMENTTYPE_RENDERBUFFER)
2255                 {
2256                         const Renderbuffer* renderbuffer = m_renderbuffers.find(attachment.name);
2257                         TCU_CHECK(renderbuffer);
2258
2259                         attachmentWidth         = renderbuffer->getWidth();
2260                         attachmentHeight        = renderbuffer->getHeight();
2261                         attachmentFormat        = renderbuffer->getFormat();
2262                 }
2263                 else
2264                 {
2265                         TCU_CHECK(attachment.type == Framebuffer::ATTACHMENTTYPE_LAST);
2266                         continue; // Skip rest of checks.
2267                 }
2268
2269                 if (!hasAttachment && attachmentWidth > 0 && attachmentHeight > 0)
2270                 {
2271                         width                   = attachmentWidth;
2272                         height                  = attachmentHeight;
2273                         hasAttachment   = true;
2274                 }
2275                 else if (attachmentWidth != width || attachmentHeight != height)
2276                         dimensionsOk = false;
2277
2278                 // Validate attachment point compatibility.
2279                 switch (attachmentFormat.order)
2280                 {
2281                         case TextureFormat::R:
2282                         case TextureFormat::RG:
2283                         case TextureFormat::RGB:
2284                         case TextureFormat::RGBA:
2285                         case TextureFormat::sRGB:
2286                         case TextureFormat::sRGBA:
2287                                 if (point != Framebuffer::ATTACHMENTPOINT_COLOR0)
2288                                         attachmentComplete = false;
2289                                 break;
2290
2291                         case TextureFormat::D:
2292                                 if (point != Framebuffer::ATTACHMENTPOINT_DEPTH)
2293                                         attachmentComplete = false;
2294                                 break;
2295
2296                         case TextureFormat::S:
2297                                 if (point != Framebuffer::ATTACHMENTPOINT_STENCIL)
2298                                         attachmentComplete = false;
2299                                 break;
2300
2301                         case TextureFormat::DS:
2302                                 if (point != Framebuffer::ATTACHMENTPOINT_DEPTH &&
2303                                         point != Framebuffer::ATTACHMENTPOINT_STENCIL)
2304                                         attachmentComplete = false;
2305                                 break;
2306
2307                         default:
2308                                 TCU_FAIL("Unsupported attachment channel order");
2309                 }
2310         }
2311
2312         if (!attachmentComplete)
2313                 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
2314         else if (!hasAttachment)
2315                 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
2316         else if (!dimensionsOk)
2317                 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
2318         else
2319                 return GL_FRAMEBUFFER_COMPLETE;
2320 }
2321
2322 void ReferenceContext::getFramebufferAttachmentParameteriv (deUint32 target, deUint32 attachment, deUint32 pname, int* params)
2323 {
2324         DE_UNREF(target && attachment && pname && params);
2325         TCU_CHECK(false); // \todo [pyry] Implement
2326 }
2327
2328 void ReferenceContext::renderbufferStorage (deUint32 target, deUint32 internalformat, int width, int height)
2329 {
2330         TextureFormat format = glu::mapGLInternalFormat(internalformat);
2331
2332         RC_IF_ERROR(target != GL_RENDERBUFFER, GL_INVALID_ENUM, RC_RET_VOID);
2333         RC_IF_ERROR(!m_renderbufferBinding, GL_INVALID_OPERATION, RC_RET_VOID);
2334         RC_IF_ERROR(!deInRange32(width, 0, m_limits.maxRenderbufferSize) ||
2335                                 !deInRange32(height, 0, m_limits.maxRenderbufferSize),
2336                                 GL_INVALID_OPERATION, RC_RET_VOID);
2337         RC_IF_ERROR(format.order == TextureFormat::CHANNELORDER_LAST ||
2338                                 format.type == TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
2339
2340         m_renderbufferBinding->setStorage(format, (int)width, (int)height);
2341 }
2342
2343 void ReferenceContext::renderbufferStorageMultisample (deUint32 target, int samples, deUint32 internalFormat, int width, int height)
2344 {
2345         // \todo [2012-04-07 pyry] Implement MSAA support.
2346         DE_UNREF(samples);
2347         renderbufferStorage(target, internalFormat, width, height);
2348 }
2349
2350 tcu::PixelBufferAccess ReferenceContext::getFboAttachment (const rc::Framebuffer& framebuffer, rc::Framebuffer::AttachmentPoint point)
2351 {
2352         const Framebuffer::Attachment& attachment = framebuffer.getAttachment(point);
2353
2354         switch (attachment.type)
2355         {
2356                 case Framebuffer::ATTACHMENTTYPE_TEXTURE:
2357                 {
2358                         Texture* texture = m_textures.find(attachment.name);
2359                         TCU_CHECK(texture);
2360
2361                         if (texture->getType() == Texture::TYPE_2D)
2362                         {
2363                                 if (Texture2D* texture2D = dynamic_cast<Texture2D*>(texture))
2364                                         return texture2D->getLevel(attachment.level);
2365                                 else
2366                                         return nullAccess();
2367                         }
2368                         else if (texture->getType() == Texture::TYPE_CUBE_MAP)
2369                         {
2370                                 if (TextureCube* cubeMap = dynamic_cast<TextureCube*>(texture))
2371                                         return cubeMap->getFace(attachment.level, texTargetToFace(attachment.texTarget));
2372                                 else
2373                                         return nullAccess();
2374                         }
2375                         else if (texture->getType() == Texture::TYPE_2D_ARRAY   ||
2376                                          texture->getType() == Texture::TYPE_3D                 ||
2377                                          texture->getType() == Texture::TYPE_CUBE_MAP_ARRAY)
2378                         {
2379                                 tcu::PixelBufferAccess level;
2380
2381                                 if (texture->getType() == Texture::TYPE_2D_ARRAY)
2382                                 {
2383                                         if (Texture2DArray* texture2DArray = dynamic_cast<Texture2DArray*>(texture))
2384                                                 level = texture2DArray->getLevel(attachment.level);
2385                                 }
2386                                 else if (texture->getType() == Texture::TYPE_3D)
2387                                 {
2388                                         if (Texture3D* texture3D = dynamic_cast<Texture3D*>(texture))
2389                                                 level = texture3D->getLevel(attachment.level);
2390                                 }
2391                                 else if (texture->getType() == Texture::TYPE_CUBE_MAP_ARRAY)
2392                                 {
2393                                         if (TextureCubeArray* cubeArray = dynamic_cast<TextureCubeArray*>(texture))
2394                                                 level = cubeArray->getLevel(attachment.level);
2395                                 }
2396
2397                                 void* layerData = static_cast<deUint8*>(level.getDataPtr()) + level.getSlicePitch() * attachment.layer;
2398
2399                                 return tcu::PixelBufferAccess(level.getFormat(), level.getWidth(), level.getHeight(), 1, level.getRowPitch(), 0, layerData);
2400                         }
2401                         else
2402                                 return nullAccess();
2403                 }
2404
2405                 case Framebuffer::ATTACHMENTTYPE_RENDERBUFFER:
2406                 {
2407                         Renderbuffer* rbo = m_renderbuffers.find(attachment.name);
2408                         TCU_CHECK(rbo);
2409
2410                         return rbo->getAccess();
2411                 }
2412
2413                 default:
2414                         return nullAccess();
2415         }
2416 }
2417
2418 const Texture2D& ReferenceContext::getTexture2D (int unitNdx) const
2419 {
2420         const TextureUnit& unit = m_textureUnits[unitNdx];
2421         return unit.tex2DBinding ? *unit.tex2DBinding : unit.default2DTex;
2422 }
2423
2424 const TextureCube& ReferenceContext::getTextureCube (int unitNdx) const
2425 {
2426         const TextureUnit& unit = m_textureUnits[unitNdx];
2427         return unit.texCubeBinding ? *unit.texCubeBinding : unit.defaultCubeTex;
2428 }
2429
2430 static bool isValidBufferTarget (deUint32 target)
2431 {
2432         switch (target)
2433         {
2434                 case GL_ARRAY_BUFFER:
2435                 case GL_COPY_READ_BUFFER:
2436                 case GL_COPY_WRITE_BUFFER:
2437                 case GL_DRAW_INDIRECT_BUFFER:
2438                 case GL_ELEMENT_ARRAY_BUFFER:
2439                 case GL_PIXEL_PACK_BUFFER:
2440                 case GL_PIXEL_UNPACK_BUFFER:
2441                 case GL_TRANSFORM_FEEDBACK_BUFFER:
2442                 case GL_UNIFORM_BUFFER:
2443                         return true;
2444
2445                 default:
2446                         return false;
2447         }
2448 }
2449
2450 void ReferenceContext::setBufferBinding (deUint32 target, DataBuffer* buffer)
2451 {
2452         DataBuffer** bindingPoint = DE_NULL;
2453         VertexArray* vertexArrayObject = (m_vertexArrayBinding) ? (m_vertexArrayBinding) : (&m_clientVertexArray);
2454
2455         switch (target)
2456         {
2457                 case GL_ARRAY_BUFFER:                           bindingPoint = &m_arrayBufferBinding;                                                           break;
2458                 case GL_COPY_READ_BUFFER:                       bindingPoint = &m_copyReadBufferBinding;                                                        break;
2459                 case GL_COPY_WRITE_BUFFER:                      bindingPoint = &m_copyWriteBufferBinding;                                                       break;
2460                 case GL_DRAW_INDIRECT_BUFFER:           bindingPoint = &m_drawIndirectBufferBinding;                                            break;
2461                 case GL_ELEMENT_ARRAY_BUFFER:           bindingPoint = &vertexArrayObject->m_elementArrayBufferBinding;         break;
2462                 case GL_PIXEL_PACK_BUFFER:                      bindingPoint = &m_pixelPackBufferBinding;                                                       break;
2463                 case GL_PIXEL_UNPACK_BUFFER:            bindingPoint = &m_pixelUnpackBufferBinding;                                                     break;
2464                 case GL_TRANSFORM_FEEDBACK_BUFFER:      bindingPoint = &m_transformFeedbackBufferBinding;                                       break;
2465                 case GL_UNIFORM_BUFFER:                         bindingPoint = &m_uniformBufferBinding;                                                         break;
2466                 default:
2467                         DE_ASSERT(false);
2468                         return;
2469         }
2470
2471         if (*bindingPoint)
2472         {
2473                 m_buffers.releaseReference(*bindingPoint);
2474                 *bindingPoint = DE_NULL;
2475         }
2476
2477         if (buffer)
2478                 m_buffers.acquireReference(buffer);
2479
2480         *bindingPoint = buffer;
2481 }
2482
2483 DataBuffer* ReferenceContext::getBufferBinding (deUint32 target) const
2484 {
2485         const VertexArray* vertexArrayObject = (m_vertexArrayBinding) ? (m_vertexArrayBinding) : (&m_clientVertexArray);
2486
2487         switch (target)
2488         {
2489                 case GL_ARRAY_BUFFER:                           return m_arrayBufferBinding;
2490                 case GL_COPY_READ_BUFFER:                       return m_copyReadBufferBinding;
2491                 case GL_COPY_WRITE_BUFFER:                      return m_copyWriteBufferBinding;
2492                 case GL_DRAW_INDIRECT_BUFFER:           return m_drawIndirectBufferBinding;
2493                 case GL_ELEMENT_ARRAY_BUFFER:           return vertexArrayObject->m_elementArrayBufferBinding;
2494                 case GL_PIXEL_PACK_BUFFER:                      return m_pixelPackBufferBinding;
2495                 case GL_PIXEL_UNPACK_BUFFER:            return m_pixelUnpackBufferBinding;
2496                 case GL_TRANSFORM_FEEDBACK_BUFFER:      return m_transformFeedbackBufferBinding;
2497                 case GL_UNIFORM_BUFFER:                         return m_uniformBufferBinding;
2498                 default:
2499                         DE_ASSERT(false);
2500                         return DE_NULL;
2501         }
2502 }
2503
2504 void ReferenceContext::bindBuffer (deUint32 target, deUint32 buffer)
2505 {
2506         RC_IF_ERROR(!isValidBufferTarget(target), GL_INVALID_ENUM, RC_RET_VOID);
2507
2508         rc::DataBuffer* bufObj  = DE_NULL;
2509
2510         if (buffer != 0)
2511         {
2512                 bufObj = m_buffers.find(buffer);
2513                 if (!bufObj)
2514                 {
2515                         bufObj = new DataBuffer(buffer);
2516                         m_buffers.insert(bufObj);
2517                 }
2518         }
2519
2520         setBufferBinding(target, bufObj);
2521 }
2522
2523 void ReferenceContext::genBuffers (int numBuffers, deUint32* buffers)
2524 {
2525         RC_IF_ERROR(!buffers, GL_INVALID_VALUE, RC_RET_VOID);
2526
2527         for (int ndx = 0; ndx < numBuffers; ndx++)
2528                 buffers[ndx] = m_buffers.allocateName();
2529 }
2530
2531 void ReferenceContext::deleteBuffers (int numBuffers, const deUint32* buffers)
2532 {
2533         RC_IF_ERROR(numBuffers < 0, GL_INVALID_VALUE, RC_RET_VOID);
2534
2535         for (int ndx = 0; ndx < numBuffers; ndx++)
2536         {
2537                 deUint32        buffer  = buffers[ndx];
2538                 DataBuffer*     bufObj  = DE_NULL;
2539
2540                 if (buffer == 0)
2541                         continue;
2542
2543                 bufObj = m_buffers.find(buffer);
2544
2545                 if (bufObj)
2546                         deleteBuffer(bufObj);
2547         }
2548 }
2549
2550 void ReferenceContext::deleteBuffer (DataBuffer* buffer)
2551 {
2552         static const deUint32 bindingPoints[] =
2553         {
2554                 GL_ARRAY_BUFFER,
2555                 GL_COPY_READ_BUFFER,
2556                 GL_COPY_WRITE_BUFFER,
2557                 GL_DRAW_INDIRECT_BUFFER,
2558                 GL_ELEMENT_ARRAY_BUFFER,
2559                 GL_PIXEL_PACK_BUFFER,
2560                 GL_PIXEL_UNPACK_BUFFER,
2561                 GL_TRANSFORM_FEEDBACK_BUFFER,
2562                 GL_UNIFORM_BUFFER
2563         };
2564
2565         for (int bindingNdx = 0; bindingNdx < DE_LENGTH_OF_ARRAY(bindingPoints); bindingNdx++)
2566         {
2567                 if (getBufferBinding(bindingPoints[bindingNdx]) == buffer)
2568                         setBufferBinding(bindingPoints[bindingNdx], DE_NULL);
2569         }
2570
2571         {
2572                 vector<VertexArray*> vertexArrays;
2573                 m_vertexArrays.getAll(vertexArrays);
2574                 vertexArrays.push_back(&m_clientVertexArray);
2575
2576                 for (vector<VertexArray*>::iterator i = vertexArrays.begin(); i != vertexArrays.end(); i++)
2577                 {
2578                         if ((*i)->m_elementArrayBufferBinding == buffer)
2579                         {
2580                                 m_buffers.releaseReference(buffer);
2581                                 (*i)->m_elementArrayBufferBinding = DE_NULL;
2582                         }
2583
2584                         for (size_t vertexAttribNdx = 0; vertexAttribNdx < (*i)->m_arrays.size(); ++vertexAttribNdx)
2585                         {
2586                                 if ((*i)->m_arrays[vertexAttribNdx].bufferBinding == buffer)
2587                                 {
2588                                         m_buffers.releaseReference(buffer);
2589                                         (*i)->m_arrays[vertexAttribNdx].bufferDeleted = true;
2590                                         (*i)->m_arrays[vertexAttribNdx].bufferBinding = DE_NULL;
2591                                 }
2592                         }
2593                 }
2594         }
2595
2596         DE_ASSERT(buffer->getRefCount() == 1);
2597         m_buffers.releaseReference(buffer);
2598 }
2599
2600 void ReferenceContext::bufferData (deUint32 target, deIntptr size, const void* data, deUint32 usage)
2601 {
2602         RC_IF_ERROR(!isValidBufferTarget(target), GL_INVALID_ENUM, RC_RET_VOID);
2603         RC_IF_ERROR(size < 0, GL_INVALID_VALUE, RC_RET_VOID);
2604
2605         DE_UNREF(usage);
2606
2607         DataBuffer* buffer = getBufferBinding(target);
2608         RC_IF_ERROR(!buffer, GL_INVALID_OPERATION, RC_RET_VOID);
2609
2610         DE_ASSERT((deIntptr)(int)size == size);
2611         buffer->setStorage((int)size);
2612         if (data)
2613                 deMemcpy(buffer->getData(), data, (int)size);
2614 }
2615
2616 void ReferenceContext::bufferSubData (deUint32 target, deIntptr offset, deIntptr size, const void* data)
2617 {
2618         RC_IF_ERROR(!isValidBufferTarget(target), GL_INVALID_ENUM, RC_RET_VOID);
2619         RC_IF_ERROR(offset < 0 || size < 0, GL_INVALID_VALUE, RC_RET_VOID);
2620
2621         DataBuffer* buffer = getBufferBinding(target);
2622
2623         RC_IF_ERROR(!buffer, GL_INVALID_OPERATION, RC_RET_VOID);
2624         RC_IF_ERROR((int)(offset+size) > buffer->getSize(), GL_INVALID_VALUE, RC_RET_VOID);
2625
2626         deMemcpy(buffer->getData()+offset, data, (int)size);
2627 }
2628
2629 void ReferenceContext::clearColor (float red, float green, float blue, float alpha)
2630 {
2631         m_clearColor = Vec4(de::clamp(red,      0.0f, 1.0f),
2632                                                 de::clamp(green,        0.0f, 1.0f),
2633                                                 de::clamp(blue, 0.0f, 1.0f),
2634                                                 de::clamp(alpha,        0.0f, 1.0f));
2635 }
2636
2637 void ReferenceContext::clearDepthf (float depth)
2638 {
2639         m_clearDepth = de::clamp(depth, 0.0f, 1.0f);
2640 }
2641
2642 void ReferenceContext::clearStencil (int stencil)
2643 {
2644         m_clearStencil = stencil;
2645 }
2646
2647 void ReferenceContext::scissor (int x, int y, int width, int height)
2648 {
2649         RC_IF_ERROR(width < 0 || height < 0, GL_INVALID_VALUE, RC_RET_VOID);
2650         m_scissorBox = IVec4(x, y, width, height);
2651 }
2652
2653 void ReferenceContext::enable (deUint32 cap)
2654 {
2655         switch (cap)
2656         {
2657                 case GL_BLEND:                                  m_blendEnabled                          = true; break;
2658                 case GL_SCISSOR_TEST:                   m_scissorEnabled                        = true; break;
2659                 case GL_DEPTH_TEST:                             m_depthTestEnabled                      = true; break;
2660                 case GL_STENCIL_TEST:                   m_stencilTestEnabled            = true; break;
2661                 case GL_POLYGON_OFFSET_FILL:    m_polygonOffsetFillEnabled      = true; break;
2662
2663                 case GL_FRAMEBUFFER_SRGB:
2664                         if (glu::isContextTypeGLCore(getType()))
2665                         {
2666                                 m_sRGBUpdateEnabled = true;
2667                                 break;
2668                         }
2669                         setError(GL_INVALID_ENUM);
2670                         break;
2671
2672                 case GL_DEPTH_CLAMP:
2673                         if (glu::isContextTypeGLCore(getType()))
2674                         {
2675                                 m_depthClampEnabled = true;
2676                                 break;
2677                         }
2678                         setError(GL_INVALID_ENUM);
2679                         break;
2680
2681                 case GL_DITHER:
2682                         // Not implemented - just ignored.
2683                         break;
2684
2685                 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
2686                         if (!glu::isContextTypeGLCore(getType()))
2687                         {
2688                                 m_primitiveRestartFixedIndex = true;
2689                                 break;
2690                         }
2691                         setError(GL_INVALID_ENUM);
2692                         break;
2693
2694                 case GL_PRIMITIVE_RESTART:
2695                         if (glu::isContextTypeGLCore(getType()))
2696                         {
2697                                 m_primitiveRestartSettableIndex = true;
2698                                 break;
2699                         }
2700                         setError(GL_INVALID_ENUM);
2701                         break;
2702
2703                 default:
2704                         setError(GL_INVALID_ENUM);
2705                         break;
2706         }
2707 }
2708
2709 void ReferenceContext::disable (deUint32 cap)
2710 {
2711         switch (cap)
2712         {
2713                 case GL_BLEND:                                  m_blendEnabled                          = false;        break;
2714                 case GL_SCISSOR_TEST:                   m_scissorEnabled                        = false;        break;
2715                 case GL_DEPTH_TEST:                             m_depthTestEnabled                      = false;        break;
2716                 case GL_STENCIL_TEST:                   m_stencilTestEnabled            = false;        break;
2717                 case GL_POLYGON_OFFSET_FILL:    m_polygonOffsetFillEnabled      = false;        break;
2718
2719                 case GL_FRAMEBUFFER_SRGB:
2720                         if (glu::isContextTypeGLCore(getType()))
2721                         {
2722                                 m_sRGBUpdateEnabled = false;
2723                                 break;
2724                         }
2725                         setError(GL_INVALID_ENUM);
2726                         break;
2727
2728                 case GL_DEPTH_CLAMP:
2729                         if (glu::isContextTypeGLCore(getType()))
2730                         {
2731                                 m_depthClampEnabled = false;
2732                                 break;
2733                         }
2734                         setError(GL_INVALID_ENUM);
2735                         break;
2736
2737                 case GL_DITHER:
2738                         break;
2739
2740                 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
2741                         if (!glu::isContextTypeGLCore(getType()))
2742                         {
2743                                 m_primitiveRestartFixedIndex = false;
2744                                 break;
2745                         }
2746                         setError(GL_INVALID_ENUM);
2747                         break;
2748
2749                 case GL_PRIMITIVE_RESTART:
2750                         if (glu::isContextTypeGLCore(getType()))
2751                         {
2752                                 m_primitiveRestartSettableIndex = false;
2753                                 break;
2754                         }
2755                         setError(GL_INVALID_ENUM);
2756                         break;
2757
2758                 default:
2759                         setError(GL_INVALID_ENUM);
2760                         break;
2761         }
2762 }
2763
2764 static bool isValidCompareFunc (deUint32 func)
2765 {
2766         switch (func)
2767         {
2768                 case GL_NEVER:
2769                 case GL_LESS:
2770                 case GL_LEQUAL:
2771                 case GL_GREATER:
2772                 case GL_GEQUAL:
2773                 case GL_EQUAL:
2774                 case GL_NOTEQUAL:
2775                 case GL_ALWAYS:
2776                         return true;
2777
2778                 default:
2779                         return false;
2780         }
2781 }
2782
2783 static bool isValidStencilOp (deUint32 op)
2784 {
2785         switch (op)
2786         {
2787                 case GL_KEEP:
2788                 case GL_ZERO:
2789                 case GL_REPLACE:
2790                 case GL_INCR:
2791                 case GL_INCR_WRAP:
2792                 case GL_DECR:
2793                 case GL_DECR_WRAP:
2794                 case GL_INVERT:
2795                         return true;
2796
2797                 default:
2798                         return false;
2799         }
2800 }
2801
2802 void ReferenceContext::stencilFunc (deUint32 func, int ref, deUint32 mask)
2803 {
2804         stencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
2805 }
2806
2807 void ReferenceContext::stencilFuncSeparate (deUint32 face, deUint32 func, int ref, deUint32 mask)
2808 {
2809         const bool      setFront        = face == GL_FRONT || face == GL_FRONT_AND_BACK;
2810         const bool      setBack         = face == GL_BACK || face == GL_FRONT_AND_BACK;
2811
2812         RC_IF_ERROR(!isValidCompareFunc(func), GL_INVALID_ENUM, RC_RET_VOID);
2813         RC_IF_ERROR(!setFront && !setBack, GL_INVALID_ENUM, RC_RET_VOID);
2814
2815         for (int type = 0; type < rr::FACETYPE_LAST; ++type)
2816         {
2817                 if ((type == rr::FACETYPE_FRONT && setFront) ||
2818                         (type == rr::FACETYPE_BACK && setBack))
2819                 {
2820                         m_stencil[type].func    = func;
2821                         m_stencil[type].ref             = ref;
2822                         m_stencil[type].opMask  = mask;
2823                 }
2824         }
2825 }
2826
2827 void ReferenceContext::stencilOp (deUint32 sfail, deUint32 dpfail, deUint32 dppass)
2828 {
2829         stencilOpSeparate(GL_FRONT_AND_BACK, sfail, dpfail, dppass);
2830 }
2831
2832 void ReferenceContext::stencilOpSeparate (deUint32 face, deUint32 sfail, deUint32 dpfail, deUint32 dppass)
2833 {
2834         const bool      setFront        = face == GL_FRONT || face == GL_FRONT_AND_BACK;
2835         const bool      setBack         = face == GL_BACK || face == GL_FRONT_AND_BACK;
2836
2837         RC_IF_ERROR(!isValidStencilOp(sfail)    ||
2838                                 !isValidStencilOp(dpfail)       ||
2839                                 !isValidStencilOp(dppass),
2840                                 GL_INVALID_ENUM, RC_RET_VOID);
2841         RC_IF_ERROR(!setFront && !setBack, GL_INVALID_ENUM, RC_RET_VOID);
2842
2843         for (int type = 0; type < rr::FACETYPE_LAST; ++type)
2844         {
2845                 if ((type == rr::FACETYPE_FRONT && setFront) ||
2846                         (type == rr::FACETYPE_BACK && setBack))
2847                 {
2848                         m_stencil[type].opStencilFail   = sfail;
2849                         m_stencil[type].opDepthFail             = dpfail;
2850                         m_stencil[type].opDepthPass             = dppass;
2851                 }
2852         }
2853 }
2854
2855 void ReferenceContext::depthFunc (deUint32 func)
2856 {
2857         RC_IF_ERROR(!isValidCompareFunc(func), GL_INVALID_ENUM, RC_RET_VOID);
2858         m_depthFunc = func;
2859 }
2860
2861 void ReferenceContext::depthRangef (float n, float f)
2862 {
2863         m_depthRangeNear = de::clamp(n, 0.0f, 1.0f);
2864         m_depthRangeFar = de::clamp(f, 0.0f, 1.0f);
2865 }
2866
2867 void ReferenceContext::depthRange (double n, double f)
2868 {
2869         depthRangef((float)n, (float)f);
2870 }
2871
2872 void ReferenceContext::polygonOffset (float factor, float units)
2873 {
2874         m_polygonOffsetFactor = factor;
2875         m_polygonOffsetUnits = units;
2876 }
2877
2878 void ReferenceContext::provokingVertex (deUint32 convention)
2879 {
2880         // only in core
2881         DE_ASSERT(glu::isContextTypeGLCore(getType()));
2882
2883         switch (convention)
2884         {
2885                 case GL_FIRST_VERTEX_CONVENTION:        m_provokingFirstVertexConvention = true; break;
2886                 case GL_LAST_VERTEX_CONVENTION:         m_provokingFirstVertexConvention = false; break;
2887
2888                 default:
2889                         RC_ERROR_RET(GL_INVALID_ENUM, RC_RET_VOID);
2890         }
2891 }
2892
2893 void ReferenceContext::primitiveRestartIndex (deUint32 index)
2894 {
2895         // only in core
2896         DE_ASSERT(glu::isContextTypeGLCore(getType()));
2897         m_primitiveRestartIndex = index;
2898 }
2899
2900 static inline bool isValidBlendEquation (deUint32 mode)
2901 {
2902         return mode == GL_FUNC_ADD                              ||
2903                    mode == GL_FUNC_SUBTRACT                     ||
2904                    mode == GL_FUNC_REVERSE_SUBTRACT     ||
2905                    mode == GL_MIN                                       ||
2906                    mode == GL_MAX;
2907 }
2908
2909 static bool isValidBlendFactor (deUint32 factor)
2910 {
2911         switch (factor)
2912         {
2913                 case GL_ZERO:
2914                 case GL_ONE:
2915                 case GL_SRC_COLOR:
2916                 case GL_ONE_MINUS_SRC_COLOR:
2917                 case GL_DST_COLOR:
2918                 case GL_ONE_MINUS_DST_COLOR:
2919                 case GL_SRC_ALPHA:
2920                 case GL_ONE_MINUS_SRC_ALPHA:
2921                 case GL_DST_ALPHA:
2922                 case GL_ONE_MINUS_DST_ALPHA:
2923                 case GL_CONSTANT_COLOR:
2924                 case GL_ONE_MINUS_CONSTANT_COLOR:
2925                 case GL_CONSTANT_ALPHA:
2926                 case GL_ONE_MINUS_CONSTANT_ALPHA:
2927                 case GL_SRC_ALPHA_SATURATE:
2928                         return true;
2929
2930                 default:
2931                         return false;
2932         }
2933 }
2934
2935 void ReferenceContext::blendEquation (deUint32 mode)
2936 {
2937         RC_IF_ERROR(!isValidBlendEquation(mode), GL_INVALID_ENUM, RC_RET_VOID);
2938
2939         m_blendModeRGB          = mode;
2940         m_blendModeAlpha        = mode;
2941 }
2942
2943 void ReferenceContext::blendEquationSeparate (deUint32 modeRGB, deUint32 modeAlpha)
2944 {
2945         RC_IF_ERROR(!isValidBlendEquation(modeRGB) ||
2946                                 !isValidBlendEquation(modeAlpha),
2947                                 GL_INVALID_ENUM, RC_RET_VOID);
2948
2949         m_blendModeRGB          = modeRGB;
2950         m_blendModeAlpha        = modeAlpha;
2951 }
2952
2953 void ReferenceContext::blendFunc (deUint32 src, deUint32 dst)
2954 {
2955         RC_IF_ERROR(!isValidBlendFactor(src) ||
2956                                 !isValidBlendFactor(dst),
2957                                 GL_INVALID_ENUM, RC_RET_VOID);
2958
2959         m_blendFactorSrcRGB             = src;
2960         m_blendFactorSrcAlpha   = src;
2961         m_blendFactorDstRGB             = dst;
2962         m_blendFactorDstAlpha   = dst;
2963 }
2964
2965 void ReferenceContext::blendFuncSeparate (deUint32 srcRGB, deUint32 dstRGB, deUint32 srcAlpha, deUint32 dstAlpha)
2966 {
2967         RC_IF_ERROR(!isValidBlendFactor(srcRGB)         ||
2968                                 !isValidBlendFactor(dstRGB)             ||
2969                                 !isValidBlendFactor(srcAlpha)   ||
2970                                 !isValidBlendFactor(dstAlpha),
2971                                 GL_INVALID_ENUM, RC_RET_VOID);
2972
2973         m_blendFactorSrcRGB             = srcRGB;
2974         m_blendFactorSrcAlpha   = srcAlpha;
2975         m_blendFactorDstRGB             = dstRGB;
2976         m_blendFactorDstAlpha   = dstAlpha;
2977 }
2978
2979 void ReferenceContext::blendColor (float red, float green, float blue, float alpha)
2980 {
2981         m_blendColor = Vec4(de::clamp(red,      0.0f, 1.0f),
2982                                                 de::clamp(green,        0.0f, 1.0f),
2983                                                 de::clamp(blue, 0.0f, 1.0f),
2984                                                 de::clamp(alpha,        0.0f, 1.0f));
2985 }
2986
2987 void ReferenceContext::colorMask (deBool r, deBool g, deBool b, deBool a)
2988 {
2989         m_colorMask = tcu::BVec4(!!r, !!g, !!b, !!a);
2990 }
2991
2992 void ReferenceContext::depthMask (deBool mask)
2993 {
2994         m_depthMask = !!mask;
2995 }
2996
2997 void ReferenceContext::stencilMask (deUint32 mask)
2998 {
2999         stencilMaskSeparate(GL_FRONT_AND_BACK, mask);
3000 }
3001
3002 void ReferenceContext::stencilMaskSeparate (deUint32 face, deUint32 mask)
3003 {
3004         const bool      setFront        = face == GL_FRONT || face == GL_FRONT_AND_BACK;
3005         const bool      setBack         = face == GL_BACK || face == GL_FRONT_AND_BACK;
3006
3007         RC_IF_ERROR(!setFront && !setBack, GL_INVALID_ENUM, RC_RET_VOID);
3008
3009         if (setFront)   m_stencil[rr::FACETYPE_FRONT].writeMask = mask;
3010         if (setBack)    m_stencil[rr::FACETYPE_BACK].writeMask  = mask;
3011 }
3012
3013 static int getNumStencilBits (const tcu::TextureFormat& format)
3014 {
3015         switch (format.order)
3016         {
3017                 case tcu::TextureFormat::S:
3018                         switch (format.type)
3019                         {
3020                                 case tcu::TextureFormat::UNSIGNED_INT8:         return 8;
3021                                 case tcu::TextureFormat::UNSIGNED_INT16:        return 16;
3022                                 case tcu::TextureFormat::UNSIGNED_INT32:        return 32;
3023                                 default:
3024                                         DE_ASSERT(false);
3025                                         return 0;
3026                         }
3027
3028                 case tcu::TextureFormat::DS:
3029                         switch (format.type)
3030                         {
3031                                 case tcu::TextureFormat::UNSIGNED_INT_24_8:                             return 8;
3032                                 case tcu::TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV:   return 8;
3033                                 default:
3034                                         DE_ASSERT(false);
3035                                         return 0;
3036                         }
3037
3038                 default:
3039                         DE_ASSERT(false);
3040                         return 0;
3041         }
3042 }
3043
3044 static inline deUint32 maskStencil (int numBits, deUint32 s)
3045 {
3046         return s & deBitMask32(0, numBits);
3047 }
3048
3049 static inline void writeMaskedStencil (const rr::MultisamplePixelBufferAccess& access, int s, int x, int y, deUint32 stencil, deUint32 writeMask)
3050 {
3051         DE_ASSERT(access.raw().getFormat().order == tcu::TextureFormat::S);
3052
3053         const deUint32 oldVal = access.raw().getPixelUint(s, x, y).x();
3054         const deUint32 newVal = (oldVal & ~writeMask) | (stencil & writeMask);
3055         access.raw().setPixel(tcu::UVec4(newVal, 0u, 0u, 0u), s, x, y);
3056 }
3057
3058 static inline void writeDepthOnly (const rr::MultisamplePixelBufferAccess& access, int s, int x, int y, float depth)
3059 {
3060         access.raw().setPixDepth(depth, s, x, y);
3061 }
3062
3063 static rr::MultisamplePixelBufferAccess getDepthMultisampleAccess (const rr::MultisamplePixelBufferAccess& combinedDSaccess)
3064 {
3065         return rr::MultisamplePixelBufferAccess::fromMultisampleAccess(tcu::getEffectiveDepthStencilAccess(combinedDSaccess.raw(), tcu::Sampler::MODE_DEPTH));
3066 }
3067
3068 static rr::MultisamplePixelBufferAccess getStencilMultisampleAccess (const rr::MultisamplePixelBufferAccess& combinedDSaccess)
3069 {
3070         return rr::MultisamplePixelBufferAccess::fromMultisampleAccess(tcu::getEffectiveDepthStencilAccess(combinedDSaccess.raw(), tcu::Sampler::MODE_STENCIL));
3071 }
3072
3073 deUint32 ReferenceContext::blitResolveMultisampleFramebuffer (deUint32 mask, const IVec4& srcRect, const IVec4& dstRect, bool flipX, bool flipY)
3074 {
3075         if (mask & GL_COLOR_BUFFER_BIT)
3076         {
3077                 rr::MultisampleConstPixelBufferAccess   src                     = rr::getSubregion(getReadColorbuffer(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w());
3078                 tcu::PixelBufferAccess                                  dst                     = tcu::getSubregion(getDrawColorbuffer().toSinglesampleAccess(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w());
3079                 tcu::TextureChannelClass                                dstClass        = tcu::getTextureChannelClass(dst.getFormat().type);
3080                 bool                                                                    dstIsFloat      = dstClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT           ||
3081                                                                                                                           dstClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT     ||
3082                                                                                                                           dstClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT;
3083                 bool                                                                    srcIsSRGB       = tcu::isSRGB(src.raw().getFormat());
3084                 bool                                                                    dstIsSRGB       = tcu::isSRGB(dst.getFormat());
3085                 const bool                                                              convertSRGB     = m_sRGBUpdateEnabled && glu::isContextTypeES(getType());
3086
3087                 if (!convertSRGB)
3088                 {
3089                         tcu::ConstPixelBufferAccess     srcRaw  = src.raw();
3090                         tcu::TextureFormat                      srcFmt  = toNonSRGBFormat(srcRaw.getFormat());
3091
3092                         srcRaw  = tcu::ConstPixelBufferAccess(srcFmt, srcRaw.getWidth(), srcRaw.getHeight(), srcRaw.getDepth(), srcRaw.getRowPitch(), srcRaw.getSlicePitch(), srcRaw.getDataPtr());
3093                         src             = rr::MultisampleConstPixelBufferAccess::fromMultisampleAccess(srcRaw);
3094
3095                         dst             = tcu::PixelBufferAccess(toNonSRGBFormat(dst.getFormat()), dst.getWidth(), dst.getHeight(), dst.getDepth(), dst.getRowPitch(), dst.getSlicePitch(), dst.getDataPtr());
3096                 }
3097
3098                 for (int x = 0; x < dstRect.z(); ++x)
3099                 for (int y = 0; y < dstRect.w(); ++y)
3100                 {
3101                         int srcX = (flipX) ? (srcRect.z() - x - 1) : (x);
3102                         int srcY = (flipY) ? (srcRect.z() - y - 1) : (y);
3103
3104                         if (dstIsFloat || srcIsSRGB)
3105                         {
3106                                 Vec4 p = src.raw().getPixel(0, srcX,srcY);
3107                                 dst.setPixel((dstIsSRGB && convertSRGB) ? tcu::linearToSRGB(p) : p, x, y);
3108                         }
3109                         else
3110                                 dst.setPixel(src.raw().getPixelInt(0, srcX, srcY), x, y);
3111                 }
3112         }
3113
3114         if (mask & GL_DEPTH_BUFFER_BIT)
3115         {
3116                 rr::MultisampleConstPixelBufferAccess   src     = rr::getSubregion(getReadDepthbuffer(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w());
3117                 rr::MultisamplePixelBufferAccess                dst     = rr::getSubregion(getDrawDepthbuffer(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w());
3118
3119                 for (int x = 0; x < dstRect.z(); ++x)
3120                 for (int y = 0; y < dstRect.w(); ++y)
3121                 {
3122                         int srcX = (flipX) ? (srcRect.z() - x - 1) : (x);
3123                         int srcY = (flipY) ? (srcRect.z() - y - 1) : (y);
3124
3125                         writeDepthOnly(dst, 0, x, y, src.raw().getPixel(0, srcX, srcY).x());
3126                 }
3127         }
3128
3129         if (mask & GL_STENCIL_BUFFER_BIT)
3130         {
3131                 rr::MultisampleConstPixelBufferAccess   src     = getStencilMultisampleAccess(rr::getSubregion(getReadStencilbuffer(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w()));
3132                 rr::MultisamplePixelBufferAccess                dst     = getStencilMultisampleAccess(rr::getSubregion(getDrawStencilbuffer(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w()));
3133
3134                 for (int x = 0; x < dstRect.z(); ++x)
3135                 for (int y = 0; y < dstRect.w(); ++y)
3136                 {
3137                         int                     srcX            = (flipX) ? (srcRect.z() - x - 1) : (x);
3138                         int                     srcY            = (flipY) ? (srcRect.z() - y - 1) : (y);
3139                         deUint32        srcStencil      = src.raw().getPixelUint(0, srcX, srcY).x();
3140
3141                         writeMaskedStencil(dst, 0, x, y, srcStencil, m_stencil[rr::FACETYPE_FRONT].writeMask);
3142                 }
3143         }
3144
3145         return GL_NO_ERROR;
3146 }
3147
3148 void ReferenceContext::blitFramebuffer (int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, deUint32 mask, deUint32 filter)
3149 {
3150         // p0 in inclusive, p1 exclusive.
3151         // Negative width/height means swap.
3152         bool    swapSrcX        = srcX1 < srcX0;
3153         bool    swapSrcY        = srcY1 < srcY0;
3154         bool    swapDstX        = dstX1 < dstX0;
3155         bool    swapDstY        = dstY1 < dstY0;
3156         int             srcW            = de::abs(srcX1-srcX0);
3157         int             srcH            = de::abs(srcY1-srcY0);
3158         int             dstW            = de::abs(dstX1-dstX0);
3159         int             dstH            = de::abs(dstY1-dstY0);
3160         bool    scale           = srcW != dstW || srcH != dstH;
3161         int             srcOriginX      = swapSrcX ? srcX1 : srcX0;
3162         int             srcOriginY      = swapSrcY ? srcY1 : srcY0;
3163         int             dstOriginX      = swapDstX ? dstX1 : dstX0;
3164         int             dstOriginY      = swapDstY ? dstY1 : dstY0;
3165         IVec4   srcRect         = IVec4(srcOriginX, srcOriginY, srcW, srcH);
3166         IVec4   dstRect         = IVec4(dstOriginX, dstOriginY, dstW, dstH);
3167
3168         RC_IF_ERROR(filter != GL_NEAREST && filter != GL_LINEAR, GL_INVALID_ENUM, RC_RET_VOID);
3169         RC_IF_ERROR((mask & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)) != 0 && filter != GL_NEAREST, GL_INVALID_OPERATION, RC_RET_VOID);
3170
3171         // Validate that both targets are complete.
3172         RC_IF_ERROR(checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE ||
3173                                 checkFramebufferStatus(GL_READ_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_OPERATION, RC_RET_VOID);
3174
3175         // Check samples count is valid
3176         RC_IF_ERROR(getDrawColorbuffer().getNumSamples() != 1, GL_INVALID_OPERATION, RC_RET_VOID);
3177
3178         // Check size restrictions of multisampled case
3179         if (getReadColorbuffer().getNumSamples() != 1)
3180         {
3181                 // Src and Dst rect dimensions must be the same
3182                 RC_IF_ERROR(srcW != dstW || srcH != dstH, GL_INVALID_OPERATION, RC_RET_VOID);
3183
3184                 // Framebuffer formats must match
3185                 if (mask & GL_COLOR_BUFFER_BIT)         RC_IF_ERROR(getReadColorbuffer().raw().getFormat()   != getDrawColorbuffer().raw().getFormat(),   GL_INVALID_OPERATION, RC_RET_VOID);
3186                 if (mask & GL_DEPTH_BUFFER_BIT)         RC_IF_ERROR(getReadDepthbuffer().raw().getFormat()   != getDrawDepthbuffer().raw().getFormat(),   GL_INVALID_OPERATION, RC_RET_VOID);
3187                 if (mask & GL_STENCIL_BUFFER_BIT)       RC_IF_ERROR(getReadStencilbuffer().raw().getFormat() != getDrawStencilbuffer().raw().getFormat(), GL_INVALID_OPERATION, RC_RET_VOID);
3188         }
3189
3190         // Compute actual source rect.
3191         srcRect = (mask & GL_COLOR_BUFFER_BIT)          ? intersect(srcRect, getBufferRect(getReadColorbuffer()))       : srcRect;
3192         srcRect = (mask & GL_DEPTH_BUFFER_BIT)          ? intersect(srcRect, getBufferRect(getReadDepthbuffer()))       : srcRect;
3193         srcRect = (mask & GL_STENCIL_BUFFER_BIT)        ? intersect(srcRect, getBufferRect(getReadStencilbuffer()))     : srcRect;
3194
3195         // Compute destination rect.
3196         dstRect = (mask & GL_COLOR_BUFFER_BIT)          ? intersect(dstRect, getBufferRect(getDrawColorbuffer()))       : dstRect;
3197         dstRect = (mask & GL_DEPTH_BUFFER_BIT)          ? intersect(dstRect, getBufferRect(getDrawDepthbuffer()))       : dstRect;
3198         dstRect = (mask & GL_STENCIL_BUFFER_BIT)        ? intersect(dstRect, getBufferRect(getDrawStencilbuffer()))     : dstRect;
3199         dstRect = m_scissorEnabled                                      ? intersect(dstRect, m_scissorBox)                                                      : dstRect;
3200
3201         if (isEmpty(srcRect) || isEmpty(dstRect))
3202                 return; // Don't attempt copy.
3203
3204         // Multisampled read buffer is a special case
3205         if (getReadColorbuffer().getNumSamples() != 1)
3206         {
3207                 deUint32 error = blitResolveMultisampleFramebuffer(mask, srcRect, dstRect, swapSrcX ^ swapDstX, swapSrcY ^ swapDstY);
3208
3209                 if (error != GL_NO_ERROR)
3210                         setError(error);
3211
3212                 return;
3213         }
3214
3215         // \note Multisample pixel buffers can now be accessed like non-multisampled because multisample read buffer case is already handled. => sample count must be 1
3216
3217         // Coordinate transformation:
3218         // Dst offset space -> dst rectangle space -> src rectangle space -> src offset space.
3219         tcu::Mat3 transform = tcu::translationMatrix(Vec2((float)(srcX0 - srcRect.x()), (float)(srcY0 - srcRect.y())))
3220                                                 * tcu::Mat3(Vec3((float)(srcX1-srcX0) / (float)(dstX1-dstX0),
3221                                                                                  (float)(srcY1-srcY0) / (float)(dstY1-dstY0),
3222                                                                                  1.0f))
3223                                                 * tcu::translationMatrix(Vec2((float)(dstRect.x() - dstX0), (float)(dstRect.y() - dstY0)));
3224
3225         if (mask & GL_COLOR_BUFFER_BIT)
3226         {
3227                 tcu::ConstPixelBufferAccess             src                     = tcu::getSubregion(getReadColorbuffer().toSinglesampleAccess(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w());
3228                 tcu::PixelBufferAccess                  dst                     = tcu::getSubregion(getDrawColorbuffer().toSinglesampleAccess(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w());
3229                 tcu::TextureChannelClass                dstClass        = tcu::getTextureChannelClass(dst.getFormat().type);
3230                 bool                                                    dstIsFloat      = dstClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT           ||
3231                                                                                                           dstClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT     ||
3232                                                                                                           dstClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT;
3233                 tcu::Sampler::FilterMode                sFilter         = (scale && filter == GL_LINEAR) ? tcu::Sampler::LINEAR : tcu::Sampler::NEAREST;
3234                 tcu::Sampler                                    sampler         (tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE,
3235                                                                                                          sFilter, sFilter, 0.0f /* lod threshold */, false /* non-normalized coords */);
3236                 bool                                                    srcIsSRGB       = tcu::isSRGB(src.getFormat());
3237                 bool                                                    dstIsSRGB       = tcu::isSRGB(dst.getFormat());
3238                 const bool                                              convertSRGB     = m_sRGBUpdateEnabled && glu::isContextTypeES(getType());
3239
3240                 if (!convertSRGB)
3241                 {
3242                         src     = tcu::ConstPixelBufferAccess   (toNonSRGBFormat(src.getFormat()), src.getWidth(), src.getHeight(), src.getDepth(), src.getRowPitch(), src.getSlicePitch(), src.getDataPtr());
3243                         dst     = tcu::PixelBufferAccess                (toNonSRGBFormat(dst.getFormat()), dst.getWidth(), dst.getHeight(), dst.getDepth(), dst.getRowPitch(), dst.getSlicePitch(), dst.getDataPtr());
3244                 }
3245
3246                 // \note We don't check for unsupported conversions, unlike spec requires.
3247
3248                 for (int yo = 0; yo < dstRect.w(); yo++)
3249                 {
3250                         for (int xo = 0; xo < dstRect.z(); xo++)
3251                         {
3252                                 float   dX      = (float)xo + 0.5f;
3253                                 float   dY      = (float)yo + 0.5f;
3254
3255                                 // \note Only affine part is used.
3256                                 float   sX      = transform(0, 0)*dX + transform(0, 1)*dY + transform(0, 2);
3257                                 float   sY      = transform(1, 0)*dX + transform(1, 1)*dY + transform(1, 2);
3258
3259                                 // do not copy pixels outside the modified source region (modified by buffer intersection)
3260                                 if (sX < 0.0f || sX >= (float)srcRect.z() ||
3261                                         sY < 0.0f || sY >= (float)srcRect.w())
3262                                         continue;
3263
3264                                 if (dstIsFloat || srcIsSRGB || filter == tcu::Sampler::LINEAR)
3265                                 {
3266                                         Vec4 p = src.sample2D(sampler, sampler.minFilter, sX, sY, 0);
3267                                         dst.setPixel((dstIsSRGB && convertSRGB) ? tcu::linearToSRGB(p) : p, xo, yo);
3268                                 }
3269                                 else
3270                                         dst.setPixel(src.getPixelInt(deFloorFloatToInt32(sX), deFloorFloatToInt32(sY)), xo, yo);
3271                         }
3272                 }
3273         }
3274
3275         if ((mask & GL_DEPTH_BUFFER_BIT) && m_depthMask)
3276         {
3277                 rr::MultisampleConstPixelBufferAccess   src             = getDepthMultisampleAccess(rr::getSubregion(getReadDepthbuffer(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w()));
3278                 rr::MultisamplePixelBufferAccess                dst             = getDepthMultisampleAccess(rr::getSubregion(getDrawDepthbuffer(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w()));
3279
3280                 for (int yo = 0; yo < dstRect.w(); yo++)
3281                 {
3282                         for (int xo = 0; xo < dstRect.z(); xo++)
3283                         {
3284                                 const int sampleNdx = 0; // multisample read buffer case is already handled
3285
3286                                 float   dX      = (float)xo + 0.5f;
3287                                 float   dY      = (float)yo + 0.5f;
3288                                 float   sX      = transform(0, 0)*dX + transform(0, 1)*dY + transform(0, 2);
3289                                 float   sY      = transform(1, 0)*dX + transform(1, 1)*dY + transform(1, 2);
3290
3291                                 writeDepthOnly(dst, sampleNdx, xo, yo, src.raw().getPixDepth(sampleNdx, deFloorFloatToInt32(sX), deFloorFloatToInt32(sY)));
3292                         }
3293                 }
3294         }
3295
3296         if (mask & GL_STENCIL_BUFFER_BIT)
3297         {
3298                 rr::MultisampleConstPixelBufferAccess   src     = getStencilMultisampleAccess(rr::getSubregion(getReadStencilbuffer(), srcRect.x(), srcRect.y(), srcRect.z(), srcRect.w()));
3299                 rr::MultisamplePixelBufferAccess                dst     = getStencilMultisampleAccess(rr::getSubregion(getDrawStencilbuffer(), dstRect.x(), dstRect.y(), dstRect.z(), dstRect.w()));
3300
3301                 for (int yo = 0; yo < dstRect.w(); yo++)
3302                 {
3303                         for (int xo = 0; xo < dstRect.z(); xo++)
3304                         {
3305                                 const int       sampleNdx = 0; // multisample read buffer case is already handled
3306
3307                                 float           dX                      = (float)xo + 0.5f;
3308                                 float           dY                      = (float)yo + 0.5f;
3309                                 float           sX                      = transform(0, 0)*dX + transform(0, 1)*dY + transform(0, 2);
3310                                 float           sY                      = transform(1, 0)*dX + transform(1, 1)*dY + transform(1, 2);
3311                                 deUint32        srcStencil      = src.raw().getPixelUint(sampleNdx, deFloorFloatToInt32(sX), deFloorFloatToInt32(sY)).x();
3312
3313                                 writeMaskedStencil(dst, sampleNdx, xo, yo, srcStencil, m_stencil[rr::FACETYPE_FRONT].writeMask);
3314                         }
3315                 }
3316         }
3317 }
3318
3319 void ReferenceContext::invalidateSubFramebuffer (deUint32 target, int numAttachments, const deUint32* attachments, int x, int y, int width, int height)
3320 {
3321         RC_IF_ERROR(target != GL_FRAMEBUFFER, GL_INVALID_ENUM, RC_RET_VOID);
3322         RC_IF_ERROR((numAttachments < 0) || (numAttachments > 1 && attachments == DE_NULL), GL_INVALID_VALUE, RC_RET_VOID);
3323         RC_IF_ERROR(width < 0 || height < 0, GL_INVALID_VALUE, RC_RET_VOID);
3324
3325         // \todo [2012-07-17 pyry] Support multiple color attachments.
3326
3327         const Vec4              colorClearValue         (0.0f);
3328         const float             depthClearValue         = 1.0f;
3329         const int               stencilClearValue       = 0;
3330
3331         bool                    isFboBound                      = m_drawFramebufferBinding != DE_NULL;
3332         bool                    discardBuffers[3]       = { false, false, false }; // Color, depth, stencil
3333
3334         for (int attNdx = 0; attNdx < numAttachments; attNdx++)
3335         {
3336                 bool    isColor                 = attachments[attNdx] == (isFboBound ? GL_COLOR_ATTACHMENT0             : GL_COLOR);
3337                 bool    isDepth                 = attachments[attNdx] == (isFboBound ? GL_DEPTH_ATTACHMENT              : GL_DEPTH);
3338                 bool    isStencil               = attachments[attNdx] == (isFboBound ? GL_STENCIL_ATTACHMENT    : GL_STENCIL);
3339                 bool    isDepthStencil  = isFboBound && attachments[attNdx] == GL_DEPTH_STENCIL_ATTACHMENT;
3340
3341                 RC_IF_ERROR(!isColor && !isDepth && !isStencil && !isDepthStencil, GL_INVALID_VALUE, RC_RET_VOID);
3342
3343                 if (isColor)                                            discardBuffers[0] = true;
3344                 if (isDepth || isDepthStencil)          discardBuffers[1] = true;
3345                 if (isStencil || isDepthStencil)        discardBuffers[2] = true;
3346         }
3347
3348         for (int ndx = 0; ndx < 3; ndx++)
3349         {
3350                 if (!discardBuffers[ndx])
3351                         continue;
3352
3353                 bool                                                            isColor                                 = ndx == 0;
3354                 bool                                                            isDepth                                 = ndx == 1;
3355                 bool                                                            isStencil                               = ndx == 2;
3356                 rr::MultisamplePixelBufferAccess        buf                                             = isColor ? getDrawColorbuffer()                                                                :
3357                                                                                                                                           isDepth ? getDepthMultisampleAccess(getDrawDepthbuffer())             :
3358                                                                                                                                                                 getStencilMultisampleAccess(getDrawStencilbuffer());
3359
3360                 if (isEmpty(buf))
3361                         continue;
3362
3363                 tcu::IVec4                                                      area                                    = intersect(tcu::IVec4(0, 0, buf.raw().getHeight(), buf.raw().getDepth()), tcu::IVec4(x, y, width, height));
3364                 rr::MultisamplePixelBufferAccess        access                                  = rr::getSubregion(buf, area.x(), area.y(), area.z(), area.w());
3365
3366                 if (isColor)
3367                         rr::clear(access, colorClearValue);
3368                 else if (isDepth)
3369                         rr::clear(access, tcu::Vec4(depthClearValue));
3370                 else if (isStencil)
3371                         rr::clear(access, tcu::IVec4(stencilClearValue));
3372         }
3373 }
3374
3375 void ReferenceContext::invalidateFramebuffer (deUint32 target, int numAttachments, const deUint32* attachments)
3376 {
3377         // \todo [2012-07-17 pyry] Support multiple color attachments.
3378         rr::MultisampleConstPixelBufferAccess   colorBuf0       = getDrawColorbuffer();
3379         rr::MultisampleConstPixelBufferAccess   depthBuf        = getDrawDepthbuffer();
3380         rr::MultisampleConstPixelBufferAccess   stencilBuf      = getDrawStencilbuffer();
3381         int                                                                             width           = 0;
3382         int                                                                             height          = 0;
3383
3384         width = de::max(width, colorBuf0.raw().getHeight());
3385         width = de::max(width, depthBuf.raw().getHeight());
3386         width = de::max(width, stencilBuf.raw().getHeight());
3387
3388         height = de::max(height, colorBuf0.raw().getDepth());
3389         height = de::max(height, depthBuf.raw().getDepth());
3390         height = de::max(height, stencilBuf.raw().getDepth());
3391
3392         invalidateSubFramebuffer(target, numAttachments, attachments, 0, 0, width, height);
3393 }
3394
3395 void ReferenceContext::clear (deUint32 buffers)
3396 {
3397         RC_IF_ERROR((buffers & ~(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)) != 0, GL_INVALID_VALUE, RC_RET_VOID);
3398
3399         rr::MultisamplePixelBufferAccess        colorBuf0       = getDrawColorbuffer();
3400         rr::MultisamplePixelBufferAccess        depthBuf        = getDrawDepthbuffer();
3401         rr::MultisamplePixelBufferAccess        stencilBuf      = getDrawStencilbuffer();
3402         IVec4                                                           baseArea        = m_scissorEnabled ? m_scissorBox : IVec4(0, 0, 0x7fffffff, 0x7fffffff);
3403         IVec4                                                           colorArea       = intersect(baseArea, getBufferRect(colorBuf0));
3404         IVec4                                                           depthArea       = intersect(baseArea, getBufferRect(depthBuf));
3405         IVec4                                                           stencilArea     = intersect(baseArea, getBufferRect(stencilBuf));
3406         bool                                                            hasColor0       = !isEmpty(colorArea);
3407         bool                                                            hasDepth        = !isEmpty(depthArea);
3408         bool                                                            hasStencil      = !isEmpty(stencilArea);
3409
3410         if (hasColor0 && (buffers & GL_COLOR_BUFFER_BIT) != 0)
3411         {
3412                 rr::MultisamplePixelBufferAccess        access          = rr::getSubregion(colorBuf0, colorArea.x(), colorArea.y(), colorArea.z(), colorArea.w());
3413                 bool                                                            isSRGB          = tcu::isSRGB(colorBuf0.raw().getFormat());
3414                 Vec4                                                            c                       = (isSRGB && m_sRGBUpdateEnabled) ? tcu::linearToSRGB(m_clearColor) : m_clearColor;
3415                 bool                                                            maskUsed        = !m_colorMask[0] || !m_colorMask[1] || !m_colorMask[2] || !m_colorMask[3];
3416                 bool                                                            maskZero        = !m_colorMask[0] && !m_colorMask[1] && !m_colorMask[2] && !m_colorMask[3];
3417
3418                 if (!maskUsed)
3419                         rr::clear(access, c);
3420                 else if (!maskZero)
3421                 {
3422                         for (int y = 0; y < access.raw().getDepth(); y++)
3423                                 for (int x = 0; x < access.raw().getHeight(); x++)
3424                                         for (int s = 0; s < access.getNumSamples(); s++)
3425                                                 access.raw().setPixel(tcu::select(c, access.raw().getPixel(s, x, y), m_colorMask), s, x, y);
3426                 }
3427                 // else all channels masked out
3428         }
3429
3430         if (hasDepth && (buffers & GL_DEPTH_BUFFER_BIT) != 0 && m_depthMask)
3431         {
3432                 rr::MultisamplePixelBufferAccess access = getDepthMultisampleAccess(rr::getSubregion(depthBuf, depthArea.x(), depthArea.y(), depthArea.z(), depthArea.w()));
3433                 rr::clearDepth(access, m_clearDepth);
3434         }
3435
3436         if (hasStencil && (buffers & GL_STENCIL_BUFFER_BIT) != 0)
3437         {
3438                 rr::MultisamplePixelBufferAccess        access                                  = getStencilMultisampleAccess(rr::getSubregion(stencilBuf, stencilArea.x(), stencilArea.y(), stencilArea.z(), stencilArea.w()));
3439                 int                                                                     stencilBits                             = getNumStencilBits(stencilBuf.raw().getFormat());
3440                 int                                                                     stencil                                 = maskStencil(stencilBits, m_clearStencil);
3441
3442                 if ((m_stencil[rr::FACETYPE_FRONT].writeMask & ((1u<<stencilBits)-1u)) != ((1u<<stencilBits)-1u))
3443                 {
3444                         // Slow path where depth or stencil is masked out in write.
3445                         for (int y = 0; y < access.raw().getDepth(); y++)
3446                                 for (int x = 0; x < access.raw().getHeight(); x++)
3447                                         for (int s = 0; s < access.getNumSamples(); s++)
3448                                                 writeMaskedStencil(access, s, x, y, stencil, m_stencil[rr::FACETYPE_FRONT].writeMask);
3449                 }
3450                 else
3451                         rr::clearStencil(access, stencil);
3452         }
3453 }
3454
3455 void ReferenceContext::clearBufferiv (deUint32 buffer, int drawbuffer, const int* value)
3456 {
3457         RC_IF_ERROR(buffer != GL_COLOR && buffer != GL_STENCIL, GL_INVALID_ENUM, RC_RET_VOID);
3458         RC_IF_ERROR(drawbuffer != 0, GL_INVALID_VALUE, RC_RET_VOID); // \todo [2012-04-06 pyry] MRT support.
3459
3460         IVec4 baseArea = m_scissorEnabled ? m_scissorBox : IVec4(0, 0, 0x7fffffff, 0x7fffffff);
3461
3462         if (buffer == GL_COLOR)
3463         {
3464                 rr::MultisamplePixelBufferAccess        colorBuf        = getDrawColorbuffer();
3465                 bool                                                            maskUsed        = !m_colorMask[0] || !m_colorMask[1] || !m_colorMask[2] || !m_colorMask[3];
3466                 bool                                                            maskZero        = !m_colorMask[0] && !m_colorMask[1] && !m_colorMask[2] && !m_colorMask[3];
3467                 IVec4                                                           area            = intersect(baseArea, getBufferRect(colorBuf));
3468
3469                 if (!isEmpty(area) && !maskZero)
3470                 {
3471                         rr::MultisamplePixelBufferAccess        access          = rr::getSubregion(colorBuf, area.x(), area.y(), area.z(), area.w());
3472                         IVec4                                                           color           (value[0], value[1], value[2], value[3]);
3473
3474                         if (!maskUsed)
3475                                 rr::clear(access, color);
3476                         else
3477                         {
3478                                 for (int y = 0; y < access.raw().getDepth(); y++)
3479                                         for (int x = 0; x < access.raw().getHeight(); x++)
3480                                                 for (int s = 0; s < access.getNumSamples(); s++)
3481                                                         access.raw().setPixel(tcu::select(color, access.raw().getPixelInt(s, x, y), m_colorMask), s, x, y);
3482                         }
3483                 }
3484         }
3485         else
3486         {
3487                 TCU_CHECK_INTERNAL(buffer == GL_STENCIL);
3488
3489                 rr::MultisamplePixelBufferAccess        stencilBuf      = getDrawStencilbuffer();
3490                 IVec4                                                           area            = intersect(baseArea, getBufferRect(stencilBuf));
3491
3492                 if (!isEmpty(area) && m_stencil[rr::FACETYPE_FRONT].writeMask != 0)
3493                 {
3494                         rr::MultisamplePixelBufferAccess        access          = getStencilMultisampleAccess(rr::getSubregion(stencilBuf, area.x(), area.y(), area.z(), area.w()));
3495                         int                                                                     stencil         = value[0];
3496
3497                         for (int y = 0; y < access.raw().getDepth(); y++)
3498                                 for (int x = 0; x < access.raw().getHeight(); x++)
3499                                         for (int s = 0; s < access.getNumSamples(); s++)
3500                                                 writeMaskedStencil(access, s, x, y, stencil, m_stencil[rr::FACETYPE_FRONT].writeMask);
3501                 }
3502         }
3503 }
3504
3505 void ReferenceContext::clearBufferfv (deUint32 buffer, int drawbuffer, const float* value)
3506 {
3507         RC_IF_ERROR(buffer != GL_COLOR && buffer != GL_DEPTH, GL_INVALID_ENUM, RC_RET_VOID);
3508         RC_IF_ERROR(drawbuffer != 0, GL_INVALID_VALUE, RC_RET_VOID); // \todo [2012-04-06 pyry] MRT support.
3509
3510         IVec4 baseArea = m_scissorEnabled ? m_scissorBox : IVec4(0, 0, 0x7fffffff, 0x7fffffff);
3511
3512         if (buffer == GL_COLOR)
3513         {
3514                 rr::MultisamplePixelBufferAccess        colorBuf        = getDrawColorbuffer();
3515                 bool                                                            maskUsed        = !m_colorMask[0] || !m_colorMask[1] || !m_colorMask[2] || !m_colorMask[3];
3516                 bool                                                            maskZero        = !m_colorMask[0] && !m_colorMask[1] && !m_colorMask[2] && !m_colorMask[3];
3517                 IVec4                                                           area            = intersect(baseArea, getBufferRect(colorBuf));
3518
3519                 if (!isEmpty(area) && !maskZero)
3520                 {
3521                         rr::MultisamplePixelBufferAccess        access          = rr::getSubregion(colorBuf, area.x(), area.y(), area.z(), area.w());
3522                         Vec4                                                            color           (value[0], value[1], value[2], value[3]);
3523
3524                         if (m_sRGBUpdateEnabled && tcu::isSRGB(access.raw().getFormat()))
3525                                 color = tcu::linearToSRGB(color);
3526
3527                         if (!maskUsed)
3528                                 rr::clear(access, color);
3529                         else
3530                         {
3531                                 for (int y = 0; y < access.raw().getDepth(); y++)
3532                                         for (int x = 0; x < access.raw().getHeight(); x++)
3533                                                 for (int s = 0; s < access.getNumSamples(); s++)
3534                                                         access.raw().setPixel(tcu::select(color, access.raw().getPixel(s, x, y), m_colorMask), s, x, y);
3535                         }
3536                 }
3537         }
3538         else
3539         {
3540                 TCU_CHECK_INTERNAL(buffer == GL_DEPTH);
3541
3542                 rr::MultisamplePixelBufferAccess        depthBuf        = getDrawDepthbuffer();
3543                 IVec4                                                           area            = intersect(baseArea, getBufferRect(depthBuf));
3544
3545                 if (!isEmpty(area) && m_depthMask)
3546                 {
3547                         rr::MultisamplePixelBufferAccess        access          = rr::getSubregion(depthBuf, area.x(), area.y(), area.z(), area.w());
3548                         float                                                           depth           = value[0];
3549
3550                         rr::clearDepth(access, depth);
3551                 }
3552         }
3553 }
3554
3555 void ReferenceContext::clearBufferuiv (deUint32 buffer, int drawbuffer, const deUint32* value)
3556 {
3557         RC_IF_ERROR(buffer != GL_COLOR, GL_INVALID_ENUM, RC_RET_VOID);
3558         RC_IF_ERROR(drawbuffer != 0, GL_INVALID_VALUE, RC_RET_VOID); // \todo [2012-04-06 pyry] MRT support.
3559
3560         IVec4 baseArea = m_scissorEnabled ? m_scissorBox : IVec4(0, 0, 0x7fffffff, 0x7fffffff);
3561
3562         TCU_CHECK_INTERNAL(buffer == GL_COLOR);
3563         {
3564                 rr::MultisamplePixelBufferAccess        colorBuf        = getDrawColorbuffer();
3565                 bool                                                            maskUsed        = !m_colorMask[0] || !m_colorMask[1] || !m_colorMask[2] || !m_colorMask[3];
3566                 bool                                                            maskZero        = !m_colorMask[0] && !m_colorMask[1] && !m_colorMask[2] && !m_colorMask[3];
3567                 IVec4                                                           area            = intersect(baseArea, getBufferRect(colorBuf));
3568
3569                 if (!isEmpty(area) && !maskZero)
3570                 {
3571                         rr::MultisamplePixelBufferAccess        access          = rr::getSubregion(colorBuf, area.x(), area.y(), area.z(), area.w());
3572                         tcu::UVec4                                                      color           (value[0], value[1], value[2], value[3]);
3573
3574                         if (!maskUsed)
3575                                 rr::clear(access, color.asInt());
3576                         else
3577                         {
3578                                 for (int y = 0; y < access.raw().getDepth(); y++)
3579                                         for (int x = 0; x < access.raw().getHeight(); x++)
3580                                                 for (int s = 0; s < access.getNumSamples(); s++)
3581                                                         access.raw().setPixel(tcu::select(color, access.raw().getPixelUint(s, x, y), m_colorMask), s, x, y);
3582                         }
3583                 }
3584         }
3585 }
3586
3587 void ReferenceContext::clearBufferfi (deUint32 buffer, int drawbuffer, float depth, int stencil)
3588 {
3589         RC_IF_ERROR(buffer != GL_DEPTH_STENCIL, GL_INVALID_ENUM, RC_RET_VOID);
3590         clearBufferfv(GL_DEPTH, drawbuffer, &depth);
3591         clearBufferiv(GL_STENCIL, drawbuffer, &stencil);
3592 }
3593
3594 void ReferenceContext::bindVertexArray (deUint32 array)
3595 {
3596         rc::VertexArray* vertexArrayObject = DE_NULL;
3597
3598         if (array != 0)
3599         {
3600                 vertexArrayObject = m_vertexArrays.find(array);
3601                 if (!vertexArrayObject)
3602                 {
3603                         vertexArrayObject = new rc::VertexArray(array, m_limits.maxVertexAttribs);
3604                         m_vertexArrays.insert(vertexArrayObject);
3605                 }
3606         }
3607
3608         // Create new references
3609         if (vertexArrayObject)
3610                 m_vertexArrays.acquireReference(vertexArrayObject);
3611
3612         // Remove old references
3613         if (m_vertexArrayBinding)
3614                 m_vertexArrays.releaseReference(m_vertexArrayBinding);
3615
3616         m_vertexArrayBinding = vertexArrayObject;
3617 }
3618
3619 void ReferenceContext::genVertexArrays (int numArrays, deUint32* vertexArrays)
3620 {
3621         RC_IF_ERROR(!vertexArrays, GL_INVALID_VALUE, RC_RET_VOID);
3622
3623         for (int ndx = 0; ndx < numArrays; ndx++)
3624                 vertexArrays[ndx] = m_vertexArrays.allocateName();
3625 }
3626
3627 void ReferenceContext::deleteVertexArrays (int numArrays, const deUint32* vertexArrays)
3628 {
3629         for (int i = 0; i < numArrays; i++)
3630         {
3631                 deUint32                name            = vertexArrays[i];
3632                 VertexArray*    vertexArray     = name ? m_vertexArrays.find(name) : DE_NULL;
3633
3634                 if (vertexArray)
3635                         deleteVertexArray(vertexArray);
3636         }
3637 }
3638
3639 void ReferenceContext::vertexAttribPointer (deUint32 index, int rawSize, deUint32 type, deBool normalized, int stride, const void *pointer)
3640 {
3641         const bool allowBGRA    = !glu::isContextTypeES(getType());
3642         const int effectiveSize = (allowBGRA && rawSize == GL_BGRA) ? (4) : (rawSize);
3643
3644         RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3645         RC_IF_ERROR(effectiveSize <= 0 || effectiveSize > 4, GL_INVALID_VALUE, RC_RET_VOID);
3646         RC_IF_ERROR(type != GL_BYTE                                     &&      type != GL_UNSIGNED_BYTE        &&
3647                                 type != GL_SHORT                                &&      type != GL_UNSIGNED_SHORT       &&
3648                                 type != GL_INT                                  &&      type != GL_UNSIGNED_INT         &&
3649                                 type != GL_FIXED                                &&      type != GL_DOUBLE                       &&
3650                                 type != GL_FLOAT                                &&      type != GL_HALF_FLOAT           &&
3651                                 type != GL_INT_2_10_10_10_REV   &&      type != GL_UNSIGNED_INT_2_10_10_10_REV, GL_INVALID_ENUM, RC_RET_VOID);
3652         RC_IF_ERROR(normalized != GL_TRUE && normalized != GL_FALSE, GL_INVALID_ENUM, RC_RET_VOID);
3653         RC_IF_ERROR(stride < 0, GL_INVALID_VALUE, RC_RET_VOID);
3654         RC_IF_ERROR((type == GL_INT_2_10_10_10_REV || type == GL_UNSIGNED_INT_2_10_10_10_REV) && effectiveSize != 4, GL_INVALID_OPERATION, RC_RET_VOID);
3655         RC_IF_ERROR(m_vertexArrayBinding != DE_NULL && m_arrayBufferBinding == DE_NULL && pointer != DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
3656         RC_IF_ERROR(allowBGRA && rawSize == GL_BGRA && type != GL_INT_2_10_10_10_REV && type != GL_UNSIGNED_INT_2_10_10_10_REV && type != GL_UNSIGNED_BYTE, GL_INVALID_OPERATION, RC_RET_VOID);
3657         RC_IF_ERROR(allowBGRA && rawSize == GL_BGRA && normalized == GL_FALSE, GL_INVALID_OPERATION, RC_RET_VOID);
3658
3659         rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
3660
3661         vao.m_arrays[index].size                        = rawSize;
3662         vao.m_arrays[index].stride                      = stride;
3663         vao.m_arrays[index].type                        = type;
3664         vao.m_arrays[index].normalized          = normalized == GL_TRUE;
3665         vao.m_arrays[index].integer                     = false;
3666         vao.m_arrays[index].pointer                     = pointer;
3667
3668         // acquire new reference
3669         if (m_arrayBufferBinding)
3670                 m_buffers.acquireReference(m_arrayBufferBinding);
3671
3672         // release old reference
3673         if (vao.m_arrays[index].bufferBinding)
3674                 m_buffers.releaseReference(vao.m_arrays[index].bufferBinding);
3675
3676         vao.m_arrays[index].bufferDeleted       = false;
3677         vao.m_arrays[index].bufferBinding       = m_arrayBufferBinding;
3678 }
3679
3680 void ReferenceContext::vertexAttribIPointer (deUint32 index, int size, deUint32 type, int stride, const void *pointer)
3681 {
3682         RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3683         RC_IF_ERROR(size <= 0 || size > 4, GL_INVALID_VALUE, RC_RET_VOID);
3684         RC_IF_ERROR(type != GL_BYTE                                     &&      type != GL_UNSIGNED_BYTE        &&
3685                                 type != GL_SHORT                                &&      type != GL_UNSIGNED_SHORT       &&
3686                                 type != GL_INT                                  &&      type != GL_UNSIGNED_INT, GL_INVALID_ENUM, RC_RET_VOID);
3687         RC_IF_ERROR(stride < 0, GL_INVALID_VALUE, RC_RET_VOID);
3688         RC_IF_ERROR(m_vertexArrayBinding != DE_NULL && m_arrayBufferBinding == DE_NULL && pointer != DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
3689
3690         rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
3691
3692         vao.m_arrays[index].size                        = size;
3693         vao.m_arrays[index].stride                      = stride;
3694         vao.m_arrays[index].type                        = type;
3695         vao.m_arrays[index].normalized          = false;
3696         vao.m_arrays[index].integer                     = true;
3697         vao.m_arrays[index].pointer                     = pointer;
3698
3699         // acquire new reference
3700         if (m_arrayBufferBinding)
3701                 m_buffers.acquireReference(m_arrayBufferBinding);
3702
3703         // release old reference
3704         if (vao.m_arrays[index].bufferBinding)
3705                 m_buffers.releaseReference(vao.m_arrays[index].bufferBinding);
3706
3707         vao.m_arrays[index].bufferDeleted       = false;
3708         vao.m_arrays[index].bufferBinding       = m_arrayBufferBinding;
3709 }
3710
3711 void ReferenceContext::enableVertexAttribArray (deUint32 index)
3712 {
3713         RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3714
3715         rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
3716         vao.m_arrays[index].enabled = true;
3717 }
3718
3719 void ReferenceContext::disableVertexAttribArray (deUint32 index)
3720 {
3721         RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3722
3723         rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
3724         vao.m_arrays[index].enabled = false;
3725 }
3726
3727 void ReferenceContext::vertexAttribDivisor (deUint32 index, deUint32 divisor)
3728 {
3729         RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3730
3731         rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
3732         vao.m_arrays[index].divisor = divisor;
3733 }
3734
3735 void ReferenceContext::vertexAttrib1f (deUint32 index, float x)
3736 {
3737         RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3738
3739         m_currentAttribs[index] = rr::GenericVec4(tcu::Vec4(x, 0, 0, 1));
3740 }
3741
3742 void ReferenceContext::vertexAttrib2f (deUint32 index, float x, float y)
3743 {
3744         RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3745
3746         m_currentAttribs[index] = rr::GenericVec4(tcu::Vec4(x, y, 0, 1));
3747 }
3748
3749 void ReferenceContext::vertexAttrib3f (deUint32 index, float x, float y, float z)
3750 {
3751         RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3752
3753         m_currentAttribs[index] = rr::GenericVec4(tcu::Vec4(x, y, z, 1));
3754 }
3755
3756 void ReferenceContext::vertexAttrib4f (deUint32 index, float x, float y, float z, float w)
3757 {
3758         RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3759
3760         m_currentAttribs[index] = rr::GenericVec4(tcu::Vec4(x, y, z, w));
3761 }
3762
3763 void ReferenceContext::vertexAttribI4i (deUint32 index, deInt32 x, deInt32 y, deInt32 z, deInt32 w)
3764 {
3765         RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3766
3767         m_currentAttribs[index] = rr::GenericVec4(tcu::IVec4(x, y, z, w));
3768 }
3769
3770 void ReferenceContext::vertexAttribI4ui (deUint32 index, deUint32 x, deUint32 y, deUint32 z, deUint32 w)
3771 {
3772         RC_IF_ERROR(index >= (deUint32)m_limits.maxVertexAttribs, GL_INVALID_VALUE, RC_RET_VOID);
3773
3774         m_currentAttribs[index] = rr::GenericVec4(tcu::UVec4(x, y, z, w));
3775 }
3776
3777 deInt32 ReferenceContext::getAttribLocation (deUint32 program, const char *name)
3778 {
3779         ShaderProgramObjectContainer* shaderProg = m_programs.find(program);
3780
3781         RC_IF_ERROR(shaderProg == DE_NULL, GL_INVALID_OPERATION, -1);
3782
3783         if (name)
3784         {
3785                 std::string nameString(name);
3786
3787                 for (size_t ndx = 0; ndx < shaderProg->m_program->m_attributeNames.size(); ++ndx)
3788                         if (shaderProg->m_program->m_attributeNames[ndx] == nameString)
3789                                 return (int)ndx;
3790         }
3791
3792         return -1;
3793 }
3794
3795 void ReferenceContext::uniformv (deInt32 location, glu::DataType type, deInt32 count, const void* v)
3796 {
3797         RC_IF_ERROR(m_currentProgram == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
3798
3799         std::vector<sglr::UniformSlot>& uniforms = m_currentProgram->m_program->m_uniforms;
3800
3801         if (location == -1)
3802                 return;
3803
3804         RC_IF_ERROR(location < 0 || (size_t)location >= uniforms.size(), GL_INVALID_OPERATION, RC_RET_VOID);
3805         RC_IF_ERROR(uniforms[location].type != type, GL_INVALID_OPERATION, RC_RET_VOID);
3806         RC_IF_ERROR(count != 1, GL_INVALID_OPERATION, RC_RET_VOID); // \todo [2013-12-13 pyry] Array uniforms.
3807
3808         {
3809                 const int scalarSize = glu::getDataTypeScalarSize(type);
3810                 DE_ASSERT(scalarSize*sizeof(deUint32) <= sizeof(uniforms[location].value));
3811                 deMemcpy(&uniforms[location].value, v, scalarSize*(int)sizeof(deUint32));
3812         }
3813 }
3814
3815 void ReferenceContext::uniform1iv (deInt32 location, deInt32 count, const deInt32* v)
3816 {
3817         RC_IF_ERROR(m_currentProgram == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
3818
3819         std::vector<sglr::UniformSlot>& uniforms = m_currentProgram->m_program->m_uniforms;
3820
3821         if (location == -1)
3822                 return;
3823
3824         RC_IF_ERROR(location < 0 || (size_t)location >= uniforms.size(), GL_INVALID_OPERATION, RC_RET_VOID);
3825         RC_IF_ERROR(count != 1, GL_INVALID_OPERATION, RC_RET_VOID); // \todo [2013-12-13 pyry] Array uniforms.
3826
3827         switch (uniforms[location].type)
3828         {
3829                 case glu::TYPE_INT:             uniforms[location].value.i = *v;        return;
3830
3831                 // \note texture unit is stored to value
3832                 case glu::TYPE_SAMPLER_2D:
3833                 case glu::TYPE_UINT_SAMPLER_2D:
3834                 case glu::TYPE_INT_SAMPLER_2D:
3835                 case glu::TYPE_SAMPLER_CUBE:
3836                 case glu::TYPE_UINT_SAMPLER_CUBE:
3837                 case glu::TYPE_INT_SAMPLER_CUBE:
3838                 case glu::TYPE_SAMPLER_2D_ARRAY:
3839                 case glu::TYPE_UINT_SAMPLER_2D_ARRAY:
3840                 case glu::TYPE_INT_SAMPLER_2D_ARRAY:
3841                 case glu::TYPE_SAMPLER_3D:
3842                 case glu::TYPE_UINT_SAMPLER_3D:
3843                 case glu::TYPE_INT_SAMPLER_3D:
3844                 case glu::TYPE_SAMPLER_CUBE_ARRAY:
3845                 case glu::TYPE_UINT_SAMPLER_CUBE_ARRAY:
3846                 case glu::TYPE_INT_SAMPLER_CUBE_ARRAY:
3847                         uniforms[location].value.i = *v;
3848                         return;
3849
3850                 default:
3851                         setError(GL_INVALID_OPERATION);
3852                         return;
3853         }
3854 }
3855
3856 void ReferenceContext::uniform1f (deInt32 location, const float v0)
3857 {
3858         uniform1fv(location, 1, &v0);
3859 }
3860
3861 void ReferenceContext::uniform1i (deInt32 location, deInt32 v0)
3862 {
3863         uniform1iv(location, 1, &v0);
3864 }
3865
3866 void ReferenceContext::uniform1fv (deInt32 location, deInt32 count, const float* v)
3867 {
3868         uniformv(location, glu::TYPE_FLOAT, count, v);
3869 }
3870
3871 void ReferenceContext::uniform2fv (deInt32 location, deInt32 count, const float* v)
3872 {
3873         uniformv(location, glu::TYPE_FLOAT_VEC2, count, v);
3874 }
3875
3876 void ReferenceContext::uniform3fv (deInt32 location, deInt32 count, const float* v)
3877 {
3878         uniformv(location, glu::TYPE_FLOAT_VEC3, count, v);
3879 }
3880
3881 void ReferenceContext::uniform4fv (deInt32 location, deInt32 count, const float* v)
3882 {
3883         uniformv(location, glu::TYPE_FLOAT_VEC4, count, v);
3884 }
3885
3886 void ReferenceContext::uniform2iv (deInt32 location, deInt32 count, const deInt32* v)
3887 {
3888         uniformv(location, glu::TYPE_INT_VEC2, count, v);
3889 }
3890
3891 void ReferenceContext::uniform3iv (deInt32 location, deInt32 count, const deInt32* v)
3892 {
3893         uniformv(location, glu::TYPE_INT_VEC3, count, v);
3894 }
3895
3896 void ReferenceContext::uniform4iv (deInt32 location, deInt32 count, const deInt32* v)
3897 {
3898         uniformv(location, glu::TYPE_INT_VEC4, count, v);
3899 }
3900
3901 void ReferenceContext::uniformMatrix3fv (deInt32 location, deInt32 count, deBool transpose, const float *value)
3902 {
3903         RC_IF_ERROR(m_currentProgram == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
3904
3905         std::vector<sglr::UniformSlot>& uniforms = m_currentProgram->m_program->m_uniforms;
3906
3907         if (location == -1)
3908                 return;
3909
3910         RC_IF_ERROR(location < 0 || (size_t)location >= uniforms.size(), GL_INVALID_OPERATION, RC_RET_VOID);
3911
3912         if (count == 0)
3913                 return;
3914
3915         RC_IF_ERROR(transpose != GL_TRUE && transpose != GL_FALSE, GL_INVALID_ENUM, RC_RET_VOID);
3916
3917         switch (uniforms[location].type)
3918         {
3919                 case glu::TYPE_FLOAT_MAT3:
3920                         RC_IF_ERROR(count > 1, GL_INVALID_OPERATION, RC_RET_VOID);
3921
3922                         if (transpose == GL_FALSE) // input is column major => transpose from column major to internal row major
3923                                 for (int row = 0; row < 3; ++row)
3924                                 for (int col = 0; col < 3; ++col)
3925                                         uniforms[location].value.m3[row*3+col] = value[col*3+row];
3926                         else // input is row major
3927                                 for (int row = 0; row < 3; ++row)
3928                                 for (int col = 0; col < 3; ++col)
3929                                         uniforms[location].value.m3[row*3+col] = value[row*3+col];
3930
3931                         break;
3932
3933                 default:
3934                         setError(GL_INVALID_OPERATION);
3935                         return;
3936         }
3937 }
3938
3939 void ReferenceContext::uniformMatrix4fv (deInt32 location, deInt32 count, deBool transpose, const float *value)
3940 {
3941         RC_IF_ERROR(m_currentProgram == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
3942
3943         std::vector<sglr::UniformSlot>& uniforms = m_currentProgram->m_program->m_uniforms;
3944
3945         if (location == -1)
3946                 return;
3947
3948         RC_IF_ERROR(location < 0 || (size_t)location >= uniforms.size(), GL_INVALID_OPERATION, RC_RET_VOID);
3949
3950         if (count == 0)
3951                 return;
3952
3953         RC_IF_ERROR(transpose != GL_TRUE && transpose != GL_FALSE, GL_INVALID_ENUM, RC_RET_VOID);
3954
3955         switch (uniforms[location].type)
3956         {
3957                 case glu::TYPE_FLOAT_MAT4:
3958                         RC_IF_ERROR(count > 1, GL_INVALID_OPERATION, RC_RET_VOID);
3959
3960                         if (transpose == GL_FALSE) // input is column major => transpose from column major to internal row major
3961                                 for (int row = 0; row < 4; ++row)
3962                                 for (int col = 0; col < 4; ++col)
3963                                         uniforms[location].value.m4[row*3+col] = value[col*3+row];
3964                         else // input is row major
3965                                 for (int row = 0; row < 4; ++row)
3966                                 for (int col = 0; col < 4; ++col)
3967                                         uniforms[location].value.m4[row*3+col] = value[row*3+col];
3968
3969                         break;
3970
3971                 default:
3972                         setError(GL_INVALID_OPERATION);
3973                         return;
3974         }
3975 }
3976
3977 deInt32 ReferenceContext::getUniformLocation (deUint32 program, const char *name)
3978 {
3979         ShaderProgramObjectContainer* shaderProg = m_programs.find(program);
3980         RC_IF_ERROR(shaderProg == DE_NULL, GL_INVALID_OPERATION, -1);
3981
3982         std::vector<sglr::UniformSlot>& uniforms = shaderProg->m_program->m_uniforms;
3983
3984         for (size_t i = 0; i < uniforms.size(); ++i)
3985                 if (name && deStringEqual(uniforms[i].name.c_str(), name))
3986                         return (int)i;
3987
3988         return -1;
3989 }
3990
3991 void ReferenceContext::lineWidth (float w)
3992 {
3993         RC_IF_ERROR(w < 0.0f, GL_INVALID_VALUE, RC_RET_VOID);
3994         m_lineWidth = w;
3995 }
3996
3997 void ReferenceContext::deleteVertexArray (rc::VertexArray* vertexArray)
3998 {
3999         if (m_vertexArrayBinding == vertexArray)
4000                 bindVertexArray(0);
4001
4002         if (vertexArray->m_elementArrayBufferBinding)
4003                 m_buffers.releaseReference(vertexArray->m_elementArrayBufferBinding);
4004
4005         for (size_t ndx = 0; ndx < vertexArray->m_arrays.size(); ++ndx)
4006                 if (vertexArray->m_arrays[ndx].bufferBinding)
4007                         m_buffers.releaseReference(vertexArray->m_arrays[ndx].bufferBinding);
4008
4009         DE_ASSERT(vertexArray->getRefCount() == 1);
4010         m_vertexArrays.releaseReference(vertexArray);
4011 }
4012
4013 void ReferenceContext::deleteProgramObject (rc::ShaderProgramObjectContainer* sp)
4014 {
4015         // Unbinding program will delete it
4016         if (m_currentProgram == sp && sp->m_deleteFlag)
4017         {
4018                 useProgram(0);
4019                 return;
4020         }
4021
4022         // Unbinding program will NOT delete it
4023         if (m_currentProgram == sp)
4024                 useProgram(0);
4025
4026         DE_ASSERT(sp->getRefCount() == 1);
4027         m_programs.releaseReference(sp);
4028 }
4029
4030 void ReferenceContext::drawArrays (deUint32 mode, int first, int count)
4031 {
4032         drawArraysInstanced(mode, first, count, 1);
4033 }
4034
4035 void ReferenceContext::drawArraysInstanced (deUint32 mode, int first, int count, int instanceCount)
4036 {
4037         // Error conditions
4038         {
4039                 RC_IF_ERROR(first < 0 || count < 0 || instanceCount < 0, GL_INVALID_VALUE, RC_RET_VOID);
4040
4041                 if (!predrawErrorChecks(mode))
4042                         return;
4043         }
4044
4045         // All is ok
4046         {
4047                 const rr::PrimitiveType primitiveType = sglr::rr_util::mapGLPrimitiveType(mode);
4048
4049                 drawWithReference(rr::PrimitiveList(primitiveType, count, first), instanceCount);
4050         }
4051 }
4052
4053 void ReferenceContext::drawElements (deUint32 mode, int count, deUint32 type, const void *indices)
4054 {
4055         drawElementsInstanced(mode, count, type, indices, 1);
4056 }
4057
4058 void ReferenceContext::drawElementsBaseVertex (deUint32 mode, int count, deUint32 type, const void *indices, int baseVertex)
4059 {
4060         drawElementsInstancedBaseVertex(mode, count, type, indices, 1, baseVertex);
4061 }
4062
4063 void ReferenceContext::drawElementsInstanced (deUint32 mode, int count, deUint32 type, const void *indices, int instanceCount)
4064 {
4065         drawElementsInstancedBaseVertex(mode, count, type, indices, instanceCount, 0);
4066 }
4067
4068 void ReferenceContext::drawElementsInstancedBaseVertex (deUint32 mode, int count, deUint32 type, const void *indices, int instanceCount, int baseVertex)
4069 {
4070         rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
4071
4072         // Error conditions
4073         {
4074                 RC_IF_ERROR(type != GL_UNSIGNED_BYTE &&
4075                                         type != GL_UNSIGNED_SHORT &&
4076                                         type != GL_UNSIGNED_INT, GL_INVALID_ENUM, RC_RET_VOID);
4077                 RC_IF_ERROR(count < 0 || instanceCount < 0, GL_INVALID_VALUE, RC_RET_VOID);
4078
4079                 if (!predrawErrorChecks(mode))
4080                         return;
4081         }
4082
4083         // All is ok
4084         {
4085                 const rr::PrimitiveType primitiveType   = sglr::rr_util::mapGLPrimitiveType(mode);
4086                 const void*                             indicesPtr              = (vao.m_elementArrayBufferBinding) ? (vao.m_elementArrayBufferBinding->getData() + reinterpret_cast<uintptr_t>(indices)) : (indices);
4087
4088                 drawWithReference(rr::PrimitiveList(primitiveType, count, rr::DrawIndices(indicesPtr, sglr::rr_util::mapGLIndexType(type), baseVertex)), instanceCount);
4089         }
4090 }
4091
4092 void ReferenceContext::drawRangeElements (deUint32 mode, deUint32 start, deUint32 end, int count, deUint32 type, const void *indices)
4093 {
4094         RC_IF_ERROR(end < start, GL_INVALID_VALUE, RC_RET_VOID);
4095
4096         drawElements(mode, count, type, indices);
4097 }
4098
4099 void ReferenceContext::drawRangeElementsBaseVertex (deUint32 mode, deUint32 start, deUint32 end, int count, deUint32 type, const void *indices, int baseVertex)
4100 {
4101         RC_IF_ERROR(end < start, GL_INVALID_VALUE, RC_RET_VOID);
4102
4103         drawElementsBaseVertex(mode, count, type, indices, baseVertex);
4104 }
4105
4106 void ReferenceContext::drawArraysIndirect (deUint32 mode, const void *indirect)
4107 {
4108         struct DrawArraysIndirectCommand
4109         {
4110                 deUint32 count;
4111                 deUint32 primCount;
4112                 deUint32 first;
4113                 deUint32 reservedMustBeZero;
4114         };
4115
4116         const DrawArraysIndirectCommand* command;
4117
4118         // Check errors
4119
4120         if (!predrawErrorChecks(mode))
4121                 return;
4122
4123         // Check pointer validity
4124
4125         RC_IF_ERROR(m_drawIndirectBufferBinding == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
4126         RC_IF_ERROR(!deIsAlignedPtr(indirect, 4), GL_INVALID_OPERATION, RC_RET_VOID);
4127
4128         // \note watch for overflows, indirect might be close to 0xFFFFFFFF and indirect+something might overflow
4129         RC_IF_ERROR((size_t)reinterpret_cast<uintptr_t>(indirect)                                     > (size_t)m_drawIndirectBufferBinding->getSize(), GL_INVALID_OPERATION, RC_RET_VOID);
4130         RC_IF_ERROR((size_t)reinterpret_cast<uintptr_t>(indirect) + sizeof(DrawArraysIndirectCommand) > (size_t)m_drawIndirectBufferBinding->getSize(), GL_INVALID_OPERATION, RC_RET_VOID);
4131
4132         // Check values
4133
4134         command = (const DrawArraysIndirectCommand*)(m_drawIndirectBufferBinding->getData() + reinterpret_cast<uintptr_t>(indirect));
4135         RC_IF_ERROR(command->reservedMustBeZero != 0, GL_INVALID_OPERATION, RC_RET_VOID);
4136
4137         // draw
4138         drawArraysInstanced(mode, command->first, command->count, command->primCount);
4139 }
4140
4141 void ReferenceContext::drawElementsIndirect     (deUint32 mode, deUint32 type, const void *indirect)
4142 {
4143         struct DrawElementsIndirectCommand
4144         {
4145                 deUint32 count;
4146                 deUint32 primCount;
4147                 deUint32 firstIndex;
4148                 deInt32  baseVertex;
4149                 deUint32 reservedMustBeZero;
4150         };
4151
4152         const DrawElementsIndirectCommand* command;
4153
4154         // Check errors
4155
4156         if (!predrawErrorChecks(mode))
4157                 return;
4158
4159         RC_IF_ERROR(type != GL_UNSIGNED_BYTE &&
4160                                 type != GL_UNSIGNED_SHORT &&
4161                                 type != GL_UNSIGNED_INT, GL_INVALID_ENUM, RC_RET_VOID);
4162
4163         RC_IF_ERROR(!getBufferBinding(GL_ELEMENT_ARRAY_BUFFER), GL_INVALID_OPERATION, RC_RET_VOID);
4164
4165         // Check pointer validity
4166
4167         RC_IF_ERROR(m_drawIndirectBufferBinding == DE_NULL, GL_INVALID_OPERATION, RC_RET_VOID);
4168         RC_IF_ERROR(!deIsAlignedPtr(indirect, 4), GL_INVALID_OPERATION, RC_RET_VOID);
4169
4170         // \note watch for overflows, indirect might be close to 0xFFFFFFFF and indirect+something might overflow
4171         RC_IF_ERROR((size_t)reinterpret_cast<uintptr_t>(indirect)                                       > (size_t)m_drawIndirectBufferBinding->getSize(), GL_INVALID_OPERATION, RC_RET_VOID);
4172         RC_IF_ERROR((size_t)reinterpret_cast<uintptr_t>(indirect) + sizeof(DrawElementsIndirectCommand) > (size_t)m_drawIndirectBufferBinding->getSize(), GL_INVALID_OPERATION, RC_RET_VOID);
4173
4174         // Check values
4175
4176         command = (const DrawElementsIndirectCommand*)(m_drawIndirectBufferBinding->getData() + reinterpret_cast<uintptr_t>(indirect));
4177         RC_IF_ERROR(command->reservedMustBeZero != 0, GL_INVALID_OPERATION, RC_RET_VOID);
4178
4179         // Check command error conditions
4180         RC_IF_ERROR((int)command->count < 0 || (int)command->primCount < 0, GL_INVALID_VALUE, RC_RET_VOID);
4181
4182         // Draw
4183         {
4184                 const size_t                    sizeOfType              = (type == GL_UNSIGNED_BYTE) ?  (1) : ((type == GL_UNSIGNED_SHORT) ? (2) : (4));
4185                 const void*                             indicesPtr              = glu::BufferOffsetAsPointer(command->firstIndex * sizeOfType);
4186
4187                 drawElementsInstancedBaseVertex(mode, (int)command->count, type, indicesPtr, (int)command->primCount, command->baseVertex);
4188         }
4189 }
4190
4191 void ReferenceContext::multiDrawArrays (deUint32 mode, const int* first, const int* count, int primCount)
4192 {
4193         DE_UNREF(mode);
4194         DE_UNREF(first);
4195         DE_UNREF(count);
4196         DE_UNREF(primCount);
4197
4198         // not supported in gles, prevent accidental use
4199         DE_ASSERT(false);
4200 }
4201
4202 void ReferenceContext::multiDrawElements (deUint32 mode, const int* count, deUint32 type, const void** indices, int primCount)
4203 {
4204         DE_UNREF(mode);
4205         DE_UNREF(count);
4206         DE_UNREF(type);
4207         DE_UNREF(indices);
4208         DE_UNREF(primCount);
4209
4210         // not supported in gles, prevent accidental use
4211         DE_ASSERT(false);
4212 }
4213
4214 void ReferenceContext::multiDrawElementsBaseVertex (deUint32 mode, const int* count, deUint32 type, const void** indices, int primCount, const int* baseVertex)
4215 {
4216         DE_UNREF(mode);
4217         DE_UNREF(count);
4218         DE_UNREF(type);
4219         DE_UNREF(indices);
4220         DE_UNREF(primCount);
4221         DE_UNREF(baseVertex);
4222
4223         // not supported in gles, prevent accidental use
4224         DE_ASSERT(false);
4225 }
4226
4227 bool ReferenceContext::predrawErrorChecks (deUint32 mode)
4228 {
4229         RC_IF_ERROR(mode != GL_POINTS &&
4230                                 mode != GL_LINE_STRIP && mode != GL_LINE_LOOP && mode != GL_LINES &&
4231                                 mode != GL_TRIANGLE_STRIP && mode != GL_TRIANGLE_FAN && mode != GL_TRIANGLES &&
4232                                 mode != GL_LINES_ADJACENCY && mode != GL_LINE_STRIP_ADJACENCY &&
4233                                 mode != GL_TRIANGLES_ADJACENCY && mode != GL_TRIANGLE_STRIP_ADJACENCY,
4234                                 GL_INVALID_ENUM, false);
4235
4236         // \todo [jarkko] Uncomment following code when the buffer mapping support is added
4237         //for (size_t ndx = 0; ndx < vao.m_arrays.size(); ++ndx)
4238         //      if (vao.m_arrays[ndx].enabled && vao.m_arrays[ndx].bufferBinding && vao.m_arrays[ndx].bufferBinding->isMapped)
4239         //              RC_ERROR_RET(GL_INVALID_OPERATION, RC_RET_VOID);
4240
4241         RC_IF_ERROR(checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION, false);
4242
4243         // Geometry shader checks
4244         if (m_currentProgram && m_currentProgram->m_program->m_hasGeometryShader)
4245         {
4246                 RC_IF_ERROR(m_currentProgram->m_program->rr::GeometryShader::getInputType() == rr::GEOMETRYSHADERINPUTTYPE_POINTS && mode != GL_POINTS, GL_INVALID_OPERATION, false);
4247
4248                 RC_IF_ERROR(m_currentProgram->m_program->rr::GeometryShader::getInputType() == rr::GEOMETRYSHADERINPUTTYPE_LINES &&
4249                         (mode != GL_LINES &&
4250                          mode != GL_LINE_STRIP &&
4251                          mode != GL_LINE_LOOP),
4252                          GL_INVALID_OPERATION, false);
4253
4254                 RC_IF_ERROR(m_currentProgram->m_program->rr::GeometryShader::getInputType() == rr::GEOMETRYSHADERINPUTTYPE_TRIANGLES &&
4255                         (mode != GL_TRIANGLES &&
4256                          mode != GL_TRIANGLE_STRIP &&
4257                          mode != GL_TRIANGLE_FAN),
4258                          GL_INVALID_OPERATION, false);
4259
4260                 RC_IF_ERROR(m_currentProgram->m_program->rr::GeometryShader::getInputType() == rr::GEOMETRYSHADERINPUTTYPE_LINES_ADJACENCY &&
4261                         (mode != GL_LINES_ADJACENCY &&
4262                          mode != GL_LINE_STRIP_ADJACENCY),
4263                          GL_INVALID_OPERATION, false);
4264
4265                 RC_IF_ERROR(m_currentProgram->m_program->rr::GeometryShader::getInputType() == rr::GEOMETRYSHADERINPUTTYPE_TRIANGLES_ADJACENCY &&
4266                         (mode != GL_TRIANGLES_ADJACENCY &&
4267                          mode != GL_TRIANGLE_STRIP_ADJACENCY),
4268                          GL_INVALID_OPERATION, false);
4269         }
4270
4271         return true;
4272 }
4273
4274 static rr::PrimitiveType getPrimitiveBaseType (rr::PrimitiveType derivedType)
4275 {
4276         switch (derivedType)
4277         {
4278                 case rr::PRIMITIVETYPE_TRIANGLES:
4279                 case rr::PRIMITIVETYPE_TRIANGLE_STRIP:
4280                 case rr::PRIMITIVETYPE_TRIANGLE_FAN:
4281                 case rr::PRIMITIVETYPE_TRIANGLES_ADJACENCY:
4282                 case rr::PRIMITIVETYPE_TRIANGLE_STRIP_ADJACENCY:
4283                         return rr::PRIMITIVETYPE_TRIANGLES;
4284
4285                 case rr::PRIMITIVETYPE_LINES:
4286                 case rr::PRIMITIVETYPE_LINE_STRIP:
4287                 case rr::PRIMITIVETYPE_LINE_LOOP:
4288                 case rr::PRIMITIVETYPE_LINES_ADJACENCY:
4289                 case rr::PRIMITIVETYPE_LINE_STRIP_ADJACENCY:
4290                         return rr::PRIMITIVETYPE_LINES;
4291
4292                 case rr::PRIMITIVETYPE_POINTS:
4293                         return rr::PRIMITIVETYPE_POINTS;
4294
4295                 default:
4296                         DE_ASSERT(false);
4297                         return rr::PRIMITIVETYPE_LAST;
4298         }
4299 }
4300
4301 static deUint32 getFixedRestartIndex (rr::IndexType indexType)
4302 {
4303         switch (indexType)
4304         {
4305                 case rr::INDEXTYPE_UINT8:               return 0xFF;
4306                 case rr::INDEXTYPE_UINT16:              return 0xFFFF;
4307                 case rr::INDEXTYPE_UINT32:              return 0xFFFFFFFFul;
4308
4309                 case rr::INDEXTYPE_LAST:
4310                 default:
4311                         DE_ASSERT(false);
4312                         return 0;
4313         }
4314 }
4315
4316 void ReferenceContext::drawWithReference (const rr::PrimitiveList& primitives, int instanceCount)
4317 {
4318         // undefined results
4319         if (m_currentProgram == DE_NULL)
4320                 return;
4321
4322         rr::MultisamplePixelBufferAccess        colorBuf0       = getDrawColorbuffer();
4323         rr::MultisamplePixelBufferAccess        depthBuf        = getDepthMultisampleAccess(getDrawDepthbuffer());
4324         rr::MultisamplePixelBufferAccess        stencilBuf      = getStencilMultisampleAccess(getDrawStencilbuffer());
4325         const bool                                                      hasStencil      = !isEmpty(stencilBuf);
4326         const int                                                       stencilBits     = (hasStencil) ? (getNumStencilBits(stencilBuf.raw().getFormat())) : (0);
4327
4328         const rr::RenderTarget                          renderTarget(colorBuf0, depthBuf, stencilBuf);
4329         const rr::Program                                       program         (m_currentProgram->m_program->getVertexShader(),
4330                                                                                                          m_currentProgram->m_program->getFragmentShader(),
4331                                                                                                          (m_currentProgram->m_program->m_hasGeometryShader) ? (m_currentProgram->m_program->getGeometryShader()) : (DE_NULL));
4332         rr::RenderState                                         state           ((rr::ViewportState)(colorBuf0), m_limits.subpixelBits);
4333
4334         const rr::Renderer                                      referenceRenderer;
4335         std::vector<rr::VertexAttrib>           vertexAttribs;
4336
4337         // Gen state
4338         {
4339                 const rr::PrimitiveType baseType                                                        = getPrimitiveBaseType(primitives.getPrimitiveType());
4340                 const bool                              polygonOffsetEnabled                            = (baseType == rr::PRIMITIVETYPE_TRIANGLES) ? (m_polygonOffsetFillEnabled) : (false);
4341
4342                 //state.cullMode                                                                                        = m_cullMode
4343
4344                 state.fragOps.scissorTestEnabled                                                        = m_scissorEnabled;
4345                 state.fragOps.scissorRectangle                                                          = rr::WindowRectangle(m_scissorBox.x(), m_scissorBox.y(), m_scissorBox.z(), m_scissorBox.w());
4346
4347                 state.fragOps.numStencilBits                                                            = stencilBits;
4348                 state.fragOps.stencilTestEnabled                                                        = m_stencilTestEnabled;
4349
4350                 for (int faceType = 0; faceType < rr::FACETYPE_LAST; faceType++)
4351                 {
4352                         state.fragOps.stencilStates[faceType].compMask  = m_stencil[faceType].opMask;
4353                         state.fragOps.stencilStates[faceType].writeMask = m_stencil[faceType].writeMask;
4354                         state.fragOps.stencilStates[faceType].ref               = m_stencil[faceType].ref;
4355                         state.fragOps.stencilStates[faceType].func              = sglr::rr_util::mapGLTestFunc(m_stencil[faceType].func);
4356                         state.fragOps.stencilStates[faceType].sFail             = sglr::rr_util::mapGLStencilOp(m_stencil[faceType].opStencilFail);
4357                         state.fragOps.stencilStates[faceType].dpFail    = sglr::rr_util::mapGLStencilOp(m_stencil[faceType].opDepthFail);
4358                         state.fragOps.stencilStates[faceType].dpPass    = sglr::rr_util::mapGLStencilOp(m_stencil[faceType].opDepthPass);
4359                 }
4360
4361                 state.fragOps.depthTestEnabled                                                          = m_depthTestEnabled;
4362                 state.fragOps.depthFunc                                                                         = sglr::rr_util::mapGLTestFunc(m_depthFunc);
4363                 state.fragOps.depthMask                                                                         = m_depthMask;
4364
4365                 state.fragOps.blendMode                                                                         = m_blendEnabled ? rr::BLENDMODE_STANDARD : rr::BLENDMODE_NONE;
4366                 state.fragOps.blendRGBState.equation                                            = sglr::rr_util::mapGLBlendEquation(m_blendModeRGB);
4367                 state.fragOps.blendRGBState.srcFunc                                                     = sglr::rr_util::mapGLBlendFunc(m_blendFactorSrcRGB);
4368                 state.fragOps.blendRGBState.dstFunc                                                     = sglr::rr_util::mapGLBlendFunc(m_blendFactorDstRGB);
4369                 state.fragOps.blendAState.equation                                                      = sglr::rr_util::mapGLBlendEquation(m_blendModeAlpha);
4370                 state.fragOps.blendAState.srcFunc                                                       = sglr::rr_util::mapGLBlendFunc(m_blendFactorSrcAlpha);
4371                 state.fragOps.blendAState.dstFunc                                                       = sglr::rr_util::mapGLBlendFunc(m_blendFactorDstAlpha);
4372                 state.fragOps.blendColor                                                                        = m_blendColor;
4373
4374                 state.fragOps.sRGBEnabled                                                                       = m_sRGBUpdateEnabled;
4375
4376                 state.fragOps.colorMask                                                                         = m_colorMask;
4377
4378                 state.fragOps.depthClampEnabled                                                         = m_depthClampEnabled;
4379
4380                 state.viewport.rect                                                                                     = rr::WindowRectangle(m_viewport.x(), m_viewport.y(), m_viewport.z(), m_viewport.w());
4381                 state.viewport.zn                                                                                       = m_depthRangeNear;
4382                 state.viewport.zf                                                                                       = m_depthRangeFar;
4383
4384                 //state.point.pointSize                                                                         = m_pointSize;
4385                 state.line.lineWidth                                                                            = m_lineWidth;
4386
4387                 state.fragOps.polygonOffsetEnabled                                                      = polygonOffsetEnabled;
4388                 state.fragOps.polygonOffsetFactor                                                       = m_polygonOffsetFactor;
4389                 state.fragOps.polygonOffsetUnits                                                        = m_polygonOffsetUnits;
4390
4391                 {
4392                         const rr::IndexType indexType = primitives.getIndexType();
4393
4394                         if (m_primitiveRestartFixedIndex && indexType != rr::INDEXTYPE_LAST)
4395                         {
4396                                 state.restart.enabled = true;
4397                                 state.restart.restartIndex = getFixedRestartIndex(indexType);
4398                         }
4399                         else if (m_primitiveRestartSettableIndex)
4400                         {
4401                                 // \note PRIMITIVE_RESTART is active for non-indexed (DrawArrays) operations too.
4402                                 state.restart.enabled = true;
4403                                 state.restart.restartIndex = m_primitiveRestartIndex;
4404                         }
4405                         else
4406                         {
4407                                 state.restart.enabled = false;
4408                         }
4409                 }
4410
4411                 state.provokingVertexConvention                                                         = (m_provokingFirstVertexConvention) ? (rr::PROVOKINGVERTEX_FIRST) : (rr::PROVOKINGVERTEX_LAST);
4412         }
4413
4414         // gen attributes
4415         {
4416                 rc::VertexArray& vao = (m_vertexArrayBinding) ? (*m_vertexArrayBinding) : (m_clientVertexArray);
4417
4418                 vertexAttribs.resize(vao.m_arrays.size());
4419                 for (size_t ndx = 0; ndx < vao.m_arrays.size(); ++ndx)
4420                 {
4421                         if (!vao.m_arrays[ndx].enabled)
4422                         {
4423                                 vertexAttribs[ndx].type = rr::VERTEXATTRIBTYPE_DONT_CARE; // reading with wrong type is allowed, but results are undefined
4424                                 vertexAttribs[ndx].generic = m_currentAttribs[ndx];
4425                         }
4426                         else if (vao.m_arrays[ndx].bufferDeleted)
4427                         {
4428                                 vertexAttribs[ndx].type = rr::VERTEXATTRIBTYPE_DONT_CARE; // reading from deleted buffer, output zeros
4429                                 vertexAttribs[ndx].generic = tcu::Vec4(0, 0, 0, 0);
4430                         }
4431                         else
4432                         {
4433                                 vertexAttribs[ndx].type                         = (vao.m_arrays[ndx].integer) ?
4434                                                                                                                 (sglr::rr_util::mapGLPureIntegerVertexAttributeType(vao.m_arrays[ndx].type)) :
4435                                                                                                                 (sglr::rr_util::mapGLFloatVertexAttributeType(vao.m_arrays[ndx].type, vao.m_arrays[ndx].normalized, vao.m_arrays[ndx].size, this->getType()));
4436                                 vertexAttribs[ndx].size                         = sglr::rr_util::mapGLSize(vao.m_arrays[ndx].size);
4437                                 vertexAttribs[ndx].stride                       = vao.m_arrays[ndx].stride;
4438                                 vertexAttribs[ndx].instanceDivisor      = vao.m_arrays[ndx].divisor;
4439                                 vertexAttribs[ndx].pointer                      = (vao.m_arrays[ndx].bufferBinding) ? (vao.m_arrays[ndx].bufferBinding->getData() + reinterpret_cast<uintptr_t>(vao.m_arrays[ndx].pointer)) : (vao.m_arrays[ndx].pointer);
4440                         }
4441                 }
4442         }
4443
4444         // Set shader samplers
4445         for (size_t uniformNdx = 0; uniformNdx < m_currentProgram->m_program->m_uniforms.size(); ++uniformNdx)
4446         {
4447                 const tcu::Sampler::DepthStencilMode    depthStencilMode        = tcu::Sampler::MODE_DEPTH; // \todo[jarkko] support sampler state
4448                 const int                                                               texNdx                          = m_currentProgram->m_program->m_uniforms[uniformNdx].value.i;
4449
4450                 switch (m_currentProgram->m_program->m_uniforms[uniformNdx].type)
4451                 {
4452                         case glu::TYPE_SAMPLER_1D:
4453                         case glu::TYPE_UINT_SAMPLER_1D:
4454                         case glu::TYPE_INT_SAMPLER_1D:
4455                         {
4456                                 rc::Texture1D* tex = DE_NULL;
4457
4458                                 if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
4459                                         tex = (m_textureUnits[texNdx].tex1DBinding) ? (m_textureUnits[texNdx].tex1DBinding) : (&m_textureUnits[texNdx].default1DTex);
4460
4461                                 if (tex && tex->isComplete())
4462                                 {
4463                                         tex->updateView(depthStencilMode);
4464                                         m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex1D = tex;
4465                                 }
4466                                 else
4467                                         m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex1D = &m_emptyTex1D;
4468
4469                                 break;
4470                         }
4471                         case glu::TYPE_SAMPLER_2D:
4472                         case glu::TYPE_UINT_SAMPLER_2D:
4473                         case glu::TYPE_INT_SAMPLER_2D:
4474                         {
4475                                 rc::Texture2D* tex = DE_NULL;
4476
4477                                 if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
4478                                         tex = (m_textureUnits[texNdx].tex2DBinding) ? (m_textureUnits[texNdx].tex2DBinding) : (&m_textureUnits[texNdx].default2DTex);
4479
4480                                 if (tex && tex->isComplete())
4481                                 {
4482                                         tex->updateView(depthStencilMode);
4483                                         m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex2D = tex;
4484                                 }
4485                                 else
4486                                         m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex2D = &m_emptyTex2D;
4487
4488                                 break;
4489                         }
4490                         case glu::TYPE_SAMPLER_CUBE:
4491                         case glu::TYPE_UINT_SAMPLER_CUBE:
4492                         case glu::TYPE_INT_SAMPLER_CUBE:
4493                         {
4494                                 rc::TextureCube* tex = DE_NULL;
4495
4496                                 if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
4497                                         tex = (m_textureUnits[texNdx].texCubeBinding) ? (m_textureUnits[texNdx].texCubeBinding) : (&m_textureUnits[texNdx].defaultCubeTex);
4498
4499                                 if (tex && tex->isComplete())
4500                                 {
4501                                         tex->updateView(depthStencilMode);
4502                                         m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.texCube = tex;
4503                                 }
4504                                 else
4505                                         m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.texCube = &m_emptyTexCube;
4506
4507                                 break;
4508                         }
4509                         case glu::TYPE_SAMPLER_2D_ARRAY:
4510                         case glu::TYPE_UINT_SAMPLER_2D_ARRAY:
4511                         case glu::TYPE_INT_SAMPLER_2D_ARRAY:
4512                         {
4513                                 rc::Texture2DArray* tex = DE_NULL;
4514
4515                                 if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
4516                                         tex = (m_textureUnits[texNdx].tex2DArrayBinding) ? (m_textureUnits[texNdx].tex2DArrayBinding) : (&m_textureUnits[texNdx].default2DArrayTex);
4517
4518                                 if (tex && tex->isComplete())
4519                                 {
4520                                         tex->updateView(depthStencilMode);
4521                                         m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex2DArray = tex;
4522                                 }
4523                                 else
4524                                         m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex2DArray = &m_emptyTex2DArray;
4525
4526                                 break;
4527                         }
4528                         case glu::TYPE_SAMPLER_3D:
4529                         case glu::TYPE_UINT_SAMPLER_3D:
4530                         case glu::TYPE_INT_SAMPLER_3D:
4531                         {
4532                                 rc::Texture3D* tex = DE_NULL;
4533
4534                                 if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
4535                                         tex = (m_textureUnits[texNdx].tex3DBinding) ? (m_textureUnits[texNdx].tex3DBinding) : (&m_textureUnits[texNdx].default3DTex);
4536
4537                                 if (tex && tex->isComplete())
4538                                 {
4539                                         tex->updateView(depthStencilMode);
4540                                         m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex3D = tex;
4541                                 }
4542                                 else
4543                                         m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.tex3D = &m_emptyTex3D;
4544
4545                                 break;
4546                         }
4547                         case glu::TYPE_SAMPLER_CUBE_ARRAY:
4548                         case glu::TYPE_UINT_SAMPLER_CUBE_ARRAY:
4549                         case glu::TYPE_INT_SAMPLER_CUBE_ARRAY:
4550                         {
4551                                 rc::TextureCubeArray* tex = DE_NULL;
4552
4553                                 if (texNdx >= 0 && (size_t)texNdx < m_textureUnits.size())
4554                                         tex = (m_textureUnits[texNdx].texCubeArrayBinding) ? (m_textureUnits[texNdx].texCubeArrayBinding) : (&m_textureUnits[texNdx].defaultCubeArrayTex);
4555
4556                                 if (tex && tex->isComplete())
4557                                 {
4558                                         tex->updateView(depthStencilMode);
4559                                         m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.texCubeArray = tex;
4560                                 }
4561                                 else
4562                                         m_currentProgram->m_program->m_uniforms[uniformNdx].sampler.texCubeArray = &m_emptyTexCubeArray;
4563
4564                                 break;
4565                         }
4566                         default:
4567                                 // nothing
4568                                 break;
4569                 }
4570         }
4571
4572         referenceRenderer.drawInstanced(rr::DrawCommand(state, renderTarget, program, (int)vertexAttribs.size(), &vertexAttribs[0], primitives), instanceCount);
4573 }
4574
4575 deUint32 ReferenceContext::createProgram (ShaderProgram* program)
4576 {
4577         int name = m_programs.allocateName();
4578
4579         m_programs.insert(new rc::ShaderProgramObjectContainer(name, program));
4580
4581         return name;
4582 }
4583
4584 void ReferenceContext::useProgram (deUint32 program)
4585 {
4586         rc::ShaderProgramObjectContainer* shaderProg                    = DE_NULL;
4587         rc::ShaderProgramObjectContainer* programToBeDeleted    = DE_NULL;
4588
4589         if (program)
4590         {
4591                 shaderProg = m_programs.find(program);
4592
4593                 // shader has not been linked
4594                 if (!shaderProg || shaderProg->m_deleteFlag)
4595                         RC_ERROR_RET(GL_INVALID_OPERATION, RC_RET_VOID);
4596         }
4597
4598         if (m_currentProgram && m_currentProgram->m_deleteFlag)
4599                 programToBeDeleted = m_currentProgram;
4600
4601         m_currentProgram = shaderProg;
4602
4603         if (programToBeDeleted)
4604         {
4605                 DE_ASSERT(programToBeDeleted->getRefCount() == 1);
4606                 deleteProgramObject(programToBeDeleted);
4607         }
4608 }
4609
4610 void ReferenceContext::deleteProgram (deUint32 program)
4611 {
4612         if (!program)
4613                 return;
4614
4615         rc::ShaderProgramObjectContainer* shaderProg = m_programs.find(program);
4616         if (shaderProg)
4617         {
4618                 if (shaderProg == m_currentProgram)
4619                 {
4620                         m_currentProgram->m_deleteFlag = true;
4621                 }
4622                 else
4623                 {
4624                         DE_ASSERT(shaderProg->getRefCount() == 1);
4625                         m_programs.releaseReference(shaderProg);
4626                 }
4627         }
4628 }
4629
4630 void ReferenceContext::readPixels (int x, int y, int width, int height, deUint32 format, deUint32 type, void* data)
4631 {
4632         rr::MultisamplePixelBufferAccess        src = getReadColorbuffer();
4633         TextureFormat                                           transferFmt;
4634
4635         // Map transfer format.
4636         transferFmt = glu::mapGLTransferFormat(format, type);
4637         RC_IF_ERROR(transferFmt.order   == TextureFormat::CHANNELORDER_LAST ||
4638                                 transferFmt.type        == TextureFormat::CHANNELTYPE_LAST, GL_INVALID_ENUM, RC_RET_VOID);
4639
4640         // Clamp input values
4641         const int copyX                 = deClamp32(x,          0, src.raw().getHeight());
4642         const int copyY                 = deClamp32(y,          0, src.raw().getDepth());
4643         const int copyWidth             = deClamp32(width,      0, src.raw().getHeight()-x);
4644         const int copyHeight    = deClamp32(height,     0, src.raw().getDepth()-y);
4645
4646         PixelBufferAccess dst(transferFmt, width, height, 1, deAlign32(width*transferFmt.getPixelSize(), m_pixelPackAlignment), 0, getPixelPackPtr(data));
4647         rr::resolveMultisampleColorBuffer(tcu::getSubregion(dst, 0, 0, copyWidth, copyHeight), rr::getSubregion(src, copyX, copyY, copyWidth, copyHeight));
4648 }
4649
4650 deUint32 ReferenceContext::getError (void)
4651 {
4652         deUint32 err = m_lastError;
4653         m_lastError = GL_NO_ERROR;
4654         return err;
4655 }
4656
4657 void ReferenceContext::finish (void)
4658 {
4659 }
4660
4661 inline void ReferenceContext::setError (deUint32 error)
4662 {
4663         if (m_lastError == GL_NO_ERROR)
4664                 m_lastError = error;
4665 }
4666
4667 void ReferenceContext::getIntegerv (deUint32 pname, int* param)
4668 {
4669         switch (pname)
4670         {
4671                 case GL_MAX_TEXTURE_SIZE:                       *param = m_limits.maxTexture2DSize;                     break;
4672                 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:      *param = m_limits.maxTextureCubeSize;           break;
4673                 case GL_MAX_ARRAY_TEXTURE_LAYERS:       *param = m_limits.maxTexture2DArrayLayers;      break;
4674                 case GL_MAX_3D_TEXTURE_SIZE:            *param = m_limits.maxTexture3DSize;                     break;
4675                 case GL_MAX_RENDERBUFFER_SIZE:          *param = m_limits.maxRenderbufferSize;          break;
4676                 case GL_MAX_TEXTURE_IMAGE_UNITS:        *param = m_limits.maxTextureImageUnits;         break;
4677                 case GL_MAX_VERTEX_ATTRIBS:                     *param = m_limits.maxVertexAttribs;                     break;
4678
4679                 default:
4680                         setError(GL_INVALID_ENUM);
4681                         break;
4682         }
4683 }
4684
4685 const char* ReferenceContext::getString (deUint32 pname)
4686 {
4687         switch (pname)
4688         {
4689                 case GL_EXTENSIONS:             return m_limits.extensionStr.c_str();
4690
4691                 default:
4692                         setError(GL_INVALID_ENUM);
4693                         return DE_NULL;
4694         }
4695 }
4696
4697 namespace rc
4698 {
4699
4700 TextureLevelArray::TextureLevelArray (void)
4701 {
4702 }
4703
4704 TextureLevelArray::~TextureLevelArray (void)
4705 {
4706         clear();
4707 }
4708
4709 void TextureLevelArray::clear (void)
4710 {
4711         DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(m_data) == DE_LENGTH_OF_ARRAY(m_access));
4712
4713         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(m_data); ndx++)
4714         {
4715                 m_data[ndx].clear();
4716                 m_access[ndx] = PixelBufferAccess();
4717         }
4718 }
4719
4720 void TextureLevelArray::allocLevel (int level, const tcu::TextureFormat& format, int width, int height, int depth)
4721 {
4722         const int dataSize = format.getPixelSize()*width*height*depth;
4723
4724         DE_ASSERT(deInBounds32(level, 0, DE_LENGTH_OF_ARRAY(m_data)));
4725
4726         if (hasLevel(level))
4727                 clearLevel(level);
4728
4729         m_data[level].setStorage(dataSize);
4730         m_access[level] = PixelBufferAccess(format, width, height, depth, m_data[level].getPtr());
4731 }
4732
4733 void TextureLevelArray::clearLevel (int level)
4734 {
4735         DE_ASSERT(deInBounds32(level, 0, DE_LENGTH_OF_ARRAY(m_data)));
4736
4737         m_data[level].clear();
4738         m_access[level] = PixelBufferAccess();
4739 }
4740
4741 void TextureLevelArray::updateSamplerMode (tcu::Sampler::DepthStencilMode mode)
4742 {
4743         for (int levelNdx = 0; hasLevel(levelNdx); ++levelNdx)
4744                 m_effectiveAccess[levelNdx] = tcu::getEffectiveDepthStencilAccess(m_access[levelNdx], mode);
4745 }
4746
4747 Texture::Texture (deUint32 name, Type type, deBool seamless)
4748         : NamedObject   (name)
4749         , m_type                (type)
4750         , m_immutable   (false)
4751         , m_sampler             (tcu::Sampler::REPEAT_GL,
4752                                          tcu::Sampler::REPEAT_GL,
4753                                          tcu::Sampler::REPEAT_GL,
4754                                          tcu::Sampler::NEAREST_MIPMAP_LINEAR,
4755                                          tcu::Sampler::LINEAR,
4756                                          0.0f,                          // LOD threshold
4757                                          true,                          // normalized coords
4758                                          tcu::Sampler::COMPAREMODE_NONE,
4759                                          0,                                     // cmp channel ndx
4760                                          tcu::Vec4(0.0f),       // border color
4761                                          seamless                       // seamless cube map, Default value is True.
4762                                          )
4763         , m_baseLevel   (0)
4764         , m_maxLevel    (1000)
4765 {
4766 }
4767
4768 Texture1D::Texture1D (deUint32 name)
4769         : Texture       (name, TYPE_1D)
4770         , m_view        (0, DE_NULL)
4771 {
4772 }
4773
4774 Texture1D::~Texture1D (void)
4775 {
4776 }
4777
4778 void Texture1D::allocLevel (int level, const tcu::TextureFormat& format, int width)
4779 {
4780         m_levels.allocLevel(level, format, width, 1, 1);
4781 }
4782
4783 bool Texture1D::isComplete (void) const
4784 {
4785         const int       baseLevel       = getBaseLevel();
4786
4787         if (hasLevel(baseLevel))
4788         {
4789                 const tcu::ConstPixelBufferAccess&      level0          = getLevel(baseLevel);
4790                 const bool                                                      mipmap          = isMipmapFilter(getSampler().minFilter);
4791
4792                 if (mipmap)
4793                 {
4794                         const TextureFormat&    format          = level0.getFormat();
4795                         const int                               w                       = level0.getWidth();
4796                         const int                               numLevels       = de::min(getMaxLevel()-baseLevel+1, getNumMipLevels1D(w));
4797
4798                         for (int levelNdx = 1; levelNdx < numLevels; levelNdx++)
4799                         {
4800                                 if (hasLevel(baseLevel+levelNdx))
4801                                 {
4802                                         const tcu::ConstPixelBufferAccess&      level           = getLevel(baseLevel+levelNdx);
4803                                         const int                                                       expectedW       = getMipLevelSize(w, levelNdx);
4804
4805                                         if (level.getWidth()    != expectedW    ||
4806                                                 level.getFormat()       != format)
4807                                                 return false;
4808                                 }
4809                                 else
4810                                         return false;
4811                         }
4812                 }
4813
4814                 return true;
4815         }
4816         else
4817                 return false;
4818 }
4819
4820 tcu::Vec4 Texture1D::sample (float s, float lod) const
4821 {
4822         return m_view.sample(getSampler(), s, 0.0f, lod);
4823 }
4824
4825 void Texture1D::sample4 (tcu::Vec4 output[4], const float packetTexcoords[4], float lodBias) const
4826 {
4827         const float texWidth = (float)m_view.getWidth();
4828
4829         const float dFdx0 = packetTexcoords[1] - packetTexcoords[0];
4830         const float dFdx1 = packetTexcoords[3] - packetTexcoords[2];
4831         const float dFdy0 = packetTexcoords[2] - packetTexcoords[0];
4832         const float dFdy1 = packetTexcoords[3] - packetTexcoords[1];
4833
4834         for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
4835         {
4836                 const float& dFdx = (fragNdx > 2) ? dFdx1 : dFdx0;
4837                 const float& dFdy = (fragNdx % 2) ? dFdy1 : dFdy0;
4838
4839                 const float mu = de::max(de::abs(dFdx), de::abs(dFdy));
4840                 const float p = mu * texWidth;
4841
4842                 const float     lod = deFloatLog2(p) + lodBias;
4843
4844                 output[fragNdx] = sample(packetTexcoords[fragNdx], lod);
4845         }
4846 }
4847
4848 void Texture1D::updateView (tcu::Sampler::DepthStencilMode mode)
4849 {
4850         const int baseLevel     = getBaseLevel();
4851
4852         if (hasLevel(baseLevel) && !isEmpty(getLevel(baseLevel)))
4853         {
4854                 const int       width           = getLevel(baseLevel).getWidth();
4855                 const bool      isMipmap        = isMipmapFilter(getSampler().minFilter);
4856                 const int       numLevels       = isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels1D(width)) : 1;
4857
4858                 m_levels.updateSamplerMode(mode);
4859                 m_view = tcu::Texture2DView(numLevels, m_levels.getEffectiveLevels() + baseLevel);
4860         }
4861         else
4862                 m_view = tcu::Texture2DView(0, DE_NULL);
4863 }
4864
4865 Texture2D::Texture2D (deUint32 name, bool es2)
4866         : Texture       (name, TYPE_2D)
4867         , m_view        (0, DE_NULL, es2)
4868 {
4869 }
4870
4871 Texture2D::~Texture2D (void)
4872 {
4873 }
4874
4875 void Texture2D::allocLevel (int level, const tcu::TextureFormat& format, int width, int height)
4876 {
4877         m_levels.allocLevel(level, format, width, height, 1);
4878 }
4879
4880 bool Texture2D::isComplete (void) const
4881 {
4882         const int       baseLevel       = getBaseLevel();
4883
4884         if (hasLevel(baseLevel))
4885         {
4886                 const tcu::ConstPixelBufferAccess&      level0          = getLevel(baseLevel);
4887                 const bool                                                      mipmap          = isMipmapFilter(getSampler().minFilter);
4888
4889                 if (mipmap)
4890                 {
4891                         const TextureFormat&    format          = level0.getFormat();
4892                         const int                               w                       = level0.getWidth();
4893                         const int                               h                       = level0.getHeight();
4894                         const int                               numLevels       = de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(w, h));
4895
4896                         for (int levelNdx = 1; levelNdx < numLevels; levelNdx++)
4897                         {
4898                                 if (hasLevel(baseLevel+levelNdx))
4899                                 {
4900                                         const tcu::ConstPixelBufferAccess&      level           = getLevel(baseLevel+levelNdx);
4901                                         const int                                                       expectedW       = getMipLevelSize(w, levelNdx);
4902                                         const int                                                       expectedH       = getMipLevelSize(h, levelNdx);
4903
4904                                         if (level.getWidth()    != expectedW    ||
4905                                                 level.getHeight()       != expectedH    ||
4906                                                 level.getFormat()       != format)
4907                                                 return false;
4908                                 }
4909                                 else
4910                                         return false;
4911                         }
4912                 }
4913
4914                 return true;
4915         }
4916         else
4917                 return false;
4918 }
4919
4920 void Texture2D::updateView (tcu::Sampler::DepthStencilMode mode)
4921 {
4922         const int baseLevel     = getBaseLevel();
4923
4924         if (hasLevel(baseLevel) && !isEmpty(getLevel(baseLevel)))
4925         {
4926                 // Update number of levels in mipmap pyramid.
4927                 const int       width           = getLevel(baseLevel).getWidth();
4928                 const int       height          = getLevel(baseLevel).getHeight();
4929                 const bool      isMipmap        = isMipmapFilter(getSampler().minFilter);
4930                 const int       numLevels       = isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(width, height)) : 1;
4931
4932                 m_levels.updateSamplerMode(mode);
4933                 m_view = tcu::Texture2DView(numLevels, m_levels.getEffectiveLevels() + baseLevel);
4934         }
4935         else
4936                 m_view = tcu::Texture2DView(0, DE_NULL);
4937 }
4938
4939 tcu::Vec4 Texture2D::sample (float s, float t, float lod) const
4940 {
4941         return m_view.sample(getSampler(), s, t, lod);
4942 }
4943
4944 void Texture2D::sample4 (tcu::Vec4 output[4], const tcu::Vec2 packetTexcoords[4], float lodBias) const
4945 {
4946         const float texWidth  = (float)m_view.getWidth();
4947         const float texHeight = (float)m_view.getHeight();
4948
4949         const tcu::Vec2 dFdx0 = packetTexcoords[1] - packetTexcoords[0];
4950         const tcu::Vec2 dFdx1 = packetTexcoords[3] - packetTexcoords[2];
4951         const tcu::Vec2 dFdy0 = packetTexcoords[2] - packetTexcoords[0];
4952         const tcu::Vec2 dFdy1 = packetTexcoords[3] - packetTexcoords[1];
4953
4954         for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
4955         {
4956                 const tcu::Vec2& dFdx = (fragNdx & 2) ? dFdx1 : dFdx0;
4957                 const tcu::Vec2& dFdy = (fragNdx & 1) ? dFdy1 : dFdy0;
4958
4959                 const float mu = de::max(de::abs(dFdx.x()), de::abs(dFdy.x()));
4960                 const float mv = de::max(de::abs(dFdx.y()), de::abs(dFdy.y()));
4961                 const float p = de::max(mu * texWidth, mv * texHeight);
4962
4963                 const float     lod = deFloatLog2(p) + lodBias;
4964
4965                 output[fragNdx] = sample(packetTexcoords[fragNdx].x(), packetTexcoords[fragNdx].y(), lod);
4966         }
4967 }
4968
4969 TextureCube::TextureCube (deUint32 name, deBool seamless)
4970         : Texture(name, TYPE_CUBE_MAP, seamless)
4971 {
4972 }
4973
4974 TextureCube::~TextureCube (void)
4975 {
4976 }
4977
4978 void TextureCube::clearLevels (void)
4979 {
4980         for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
4981                 m_levels[face].clear();
4982 }
4983
4984 void TextureCube::allocFace (int level, tcu::CubeFace face, const tcu::TextureFormat& format, int width, int height)
4985 {
4986         m_levels[face].allocLevel(level, format, width, height, 1);
4987 }
4988
4989 bool TextureCube::isComplete (void) const
4990 {
4991         const int       baseLevel       = getBaseLevel();
4992
4993         if (hasFace(baseLevel, tcu::CUBEFACE_NEGATIVE_X))
4994         {
4995                 const int                                       width           = getFace(baseLevel, tcu::CUBEFACE_NEGATIVE_X).getWidth();
4996                 const int                                       height          = getFace(baseLevel, tcu::CUBEFACE_NEGATIVE_X).getHeight();
4997                 const tcu::TextureFormat&       format          = getFace(baseLevel, tcu::CUBEFACE_NEGATIVE_X).getFormat();
4998                 const bool                                      mipmap          = isMipmapFilter(getSampler().minFilter);
4999                 const int                                       numLevels       = mipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(width, height)) : 1;
5000
5001                 if (width != height)
5002                         return false; // Non-square is not supported.
5003
5004                 // \note Level 0 is always checked for consistency
5005                 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
5006                 {
5007                         const int levelW        = getMipLevelSize(width,        levelNdx);
5008                         const int levelH        = getMipLevelSize(height,       levelNdx);
5009
5010                         for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
5011                         {
5012                                 if (hasFace(baseLevel+levelNdx, (tcu::CubeFace)face))
5013                                 {
5014                                         const tcu::ConstPixelBufferAccess& level = getFace(baseLevel+levelNdx, (tcu::CubeFace)face);
5015
5016                                         if (level.getWidth()    != levelW       ||
5017                                                 level.getHeight()       != levelH       ||
5018                                                 level.getFormat()       != format)
5019                                                 return false;
5020                                 }
5021                                 else
5022                                         return false;
5023                         }
5024                 }
5025
5026                 return true;
5027         }
5028         else
5029                 return false;
5030 }
5031
5032 void TextureCube::updateView (tcu::Sampler::DepthStencilMode mode)
5033 {
5034         const int                                                       baseLevel       = getBaseLevel();
5035         const tcu::ConstPixelBufferAccess*      faces[tcu::CUBEFACE_LAST];
5036
5037         deMemset(&faces[0], 0, sizeof(faces));
5038
5039         if (isComplete())
5040         {
5041                 const int       size            = getFace(baseLevel, tcu::CUBEFACE_NEGATIVE_X).getWidth();
5042                 const bool      isMipmap        = isMipmapFilter(getSampler().minFilter);
5043                 const int       numLevels       = isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels1D(size)) : 1;
5044
5045                 for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
5046                 {
5047                         m_levels[face].updateSamplerMode(mode);
5048                         faces[face] = m_levels[face].getEffectiveLevels() + baseLevel;
5049                 }
5050
5051                 m_view = tcu::TextureCubeView(numLevels, faces);
5052         }
5053         else
5054                 m_view = tcu::TextureCubeView(0, faces);
5055 }
5056
5057 tcu::Vec4 TextureCube::sample (float s, float t, float p, float lod) const
5058 {
5059         return m_view.sample(getSampler(), s, t, p, lod);
5060 }
5061
5062 void TextureCube::sample4 (tcu::Vec4 output[4], const tcu::Vec3 packetTexcoords[4], float lodBias) const
5063 {
5064         const float cubeSide = (float)m_view.getSize();
5065
5066         // Each tex coord might be in a different face.
5067
5068         for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
5069         {
5070                 const tcu::CubeFace face                = tcu::selectCubeFace(packetTexcoords[fragNdx]);
5071                 const tcu::Vec2         coords[4]       =
5072                 {
5073                         tcu::projectToFace(face, packetTexcoords[0]),
5074                         tcu::projectToFace(face, packetTexcoords[1]),
5075                         tcu::projectToFace(face, packetTexcoords[2]),
5076                         tcu::projectToFace(face, packetTexcoords[3]),
5077                 };
5078
5079                 const tcu::Vec2 dFdx0 = coords[1] - coords[0];
5080                 const tcu::Vec2 dFdx1 = coords[3] - coords[2];
5081                 const tcu::Vec2 dFdy0 = coords[2] - coords[0];
5082                 const tcu::Vec2 dFdy1 = coords[3] - coords[1];
5083
5084                 const tcu::Vec2& dFdx = (fragNdx & 2) ? dFdx1 : dFdx0;
5085                 const tcu::Vec2& dFdy = (fragNdx & 1) ? dFdy1 : dFdy0;
5086
5087                 const float mu = de::max(de::abs(dFdx.x()), de::abs(dFdy.x()));
5088                 const float mv = de::max(de::abs(dFdx.y()), de::abs(dFdy.y()));
5089                 const float p = de::max(mu * cubeSide, mv * cubeSide);
5090
5091                 const float     lod = deFloatLog2(p) + lodBias;
5092
5093                 output[fragNdx] = sample(packetTexcoords[fragNdx].x(), packetTexcoords[fragNdx].y(), packetTexcoords[fragNdx].z(), lod);
5094         }
5095 }
5096
5097 Texture2DArray::Texture2DArray (deUint32 name)
5098         : Texture       (name, TYPE_2D_ARRAY)
5099         , m_view        (0, DE_NULL)
5100 {
5101 }
5102
5103 Texture2DArray::~Texture2DArray (void)
5104 {
5105 }
5106
5107 void Texture2DArray::allocLevel (int level, const tcu::TextureFormat& format, int width, int height, int numLayers)
5108 {
5109         m_levels.allocLevel(level, format, width, height, numLayers);
5110 }
5111
5112 bool Texture2DArray::isComplete (void) const
5113 {
5114         const int       baseLevel       = getBaseLevel();
5115
5116         if (hasLevel(baseLevel))
5117         {
5118                 const tcu::ConstPixelBufferAccess&      level0          = getLevel(baseLevel);
5119                 const bool                                                      mipmap          = isMipmapFilter(getSampler().minFilter);
5120
5121                 if (mipmap)
5122                 {
5123                         const TextureFormat&    format          = level0.getFormat();
5124                         const int                               w                       = level0.getWidth();
5125                         const int                               h                       = level0.getHeight();
5126                         const int                               numLayers       = level0.getDepth();
5127                         const int                               numLevels       = de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(w, h));
5128
5129                         for (int levelNdx = 1; levelNdx < numLevels; levelNdx++)
5130                         {
5131                                 if (hasLevel(baseLevel+levelNdx))
5132                                 {
5133                                         const tcu::ConstPixelBufferAccess&      level           = getLevel(baseLevel+levelNdx);
5134                                         const int                                                       expectedW       = getMipLevelSize(w, levelNdx);
5135                                         const int                                                       expectedH       = getMipLevelSize(h, levelNdx);
5136
5137                                         if (level.getWidth()    != expectedW    ||
5138                                                 level.getHeight()       != expectedH    ||
5139                                                 level.getDepth()        != numLayers    ||
5140                                                 level.getFormat()       != format)
5141                                                 return false;
5142                                 }
5143                                 else
5144                                         return false;
5145                         }
5146                 }
5147
5148                 return true;
5149         }
5150         else
5151                 return false;
5152 }
5153
5154 void Texture2DArray::updateView (tcu::Sampler::DepthStencilMode mode)
5155 {
5156         const int baseLevel     = getBaseLevel();
5157
5158         if (hasLevel(baseLevel) && !isEmpty(getLevel(baseLevel)))
5159         {
5160                 const int       width           = getLevel(baseLevel).getWidth();
5161                 const int       height          = getLevel(baseLevel).getHeight();
5162                 const bool      isMipmap        = isMipmapFilter(getSampler().minFilter);
5163                 const int       numLevels       = isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(width, height)) : 1;
5164
5165                 m_levels.updateSamplerMode(mode);
5166                 m_view = tcu::Texture2DArrayView(numLevels, m_levels.getEffectiveLevels() + baseLevel);
5167         }
5168         else
5169                 m_view = tcu::Texture2DArrayView(0, DE_NULL);
5170 }
5171
5172 tcu::Vec4 Texture2DArray::sample (float s, float t, float r, float lod) const
5173 {
5174         return m_view.sample(getSampler(), s, t, r, lod);
5175 }
5176
5177 void Texture2DArray::sample4 (tcu::Vec4 output[4], const tcu::Vec3 packetTexcoords[4], float lodBias) const
5178 {
5179         const float texWidth  = (float)m_view.getWidth();
5180         const float texHeight = (float)m_view.getHeight();
5181
5182         const tcu::Vec3 dFdx0 = packetTexcoords[1] - packetTexcoords[0];
5183         const tcu::Vec3 dFdx1 = packetTexcoords[3] - packetTexcoords[2];
5184         const tcu::Vec3 dFdy0 = packetTexcoords[2] - packetTexcoords[0];
5185         const tcu::Vec3 dFdy1 = packetTexcoords[3] - packetTexcoords[1];
5186
5187         for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
5188         {
5189                 const tcu::Vec3& dFdx = (fragNdx & 2) ? dFdx1 : dFdx0;
5190                 const tcu::Vec3& dFdy = (fragNdx & 1) ? dFdy1 : dFdy0;
5191
5192                 const float mu = de::max(de::abs(dFdx.x()), de::abs(dFdy.x()));
5193                 const float mv = de::max(de::abs(dFdx.y()), de::abs(dFdy.y()));
5194                 const float p = de::max(mu * texWidth, mv * texHeight);
5195
5196                 const float     lod = deFloatLog2(p) + lodBias;
5197
5198                 output[fragNdx] = sample(packetTexcoords[fragNdx].x(), packetTexcoords[fragNdx].y(), packetTexcoords[fragNdx].z(), lod);
5199         }
5200 }
5201
5202 TextureCubeArray::TextureCubeArray (deUint32 name)
5203         : Texture       (name, TYPE_CUBE_MAP_ARRAY)
5204         , m_view        (0, DE_NULL)
5205 {
5206 }
5207
5208 TextureCubeArray::~TextureCubeArray (void)
5209 {
5210 }
5211
5212 void TextureCubeArray::allocLevel (int level, const tcu::TextureFormat& format, int width, int height, int numLayers)
5213 {
5214         DE_ASSERT(numLayers % 6 == 0);
5215         m_levels.allocLevel(level, format, width, height, numLayers);
5216 }
5217
5218 bool TextureCubeArray::isComplete (void) const
5219 {
5220         const int       baseLevel       = getBaseLevel();
5221
5222         if (hasLevel(baseLevel))
5223         {
5224                 const tcu::ConstPixelBufferAccess&      level0          = getLevel(baseLevel);
5225                 const bool                                                      mipmap          = isMipmapFilter(getSampler().minFilter);
5226
5227                 if (mipmap)
5228                 {
5229                         const TextureFormat&    format          = level0.getFormat();
5230                         const int                               w                       = level0.getWidth();
5231                         const int                               h                       = level0.getHeight();
5232                         const int                               numLayers       = level0.getDepth();
5233                         const int                               numLevels       = de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(w, h));
5234
5235                         for (int levelNdx = 1; levelNdx < numLevels; levelNdx++)
5236                         {
5237                                 if (hasLevel(baseLevel+levelNdx))
5238                                 {
5239                                         const tcu::ConstPixelBufferAccess&      level           = getLevel(baseLevel+levelNdx);
5240                                         const int                                                       expectedW       = getMipLevelSize(w, levelNdx);
5241                                         const int                                                       expectedH       = getMipLevelSize(h, levelNdx);
5242
5243                                         if (level.getWidth()    != expectedW    ||
5244                                                 level.getHeight()       != expectedH    ||
5245                                                 level.getDepth()        != numLayers    ||
5246                                                 level.getFormat()       != format)
5247                                                 return false;
5248                                 }
5249                                 else
5250                                         return false;
5251                         }
5252                 }
5253
5254                 return true;
5255         }
5256         else
5257                 return false;
5258 }
5259
5260 void TextureCubeArray::updateView (tcu::Sampler::DepthStencilMode mode)
5261 {
5262         const int baseLevel     = getBaseLevel();
5263
5264         if (hasLevel(baseLevel) && !isEmpty(getLevel(baseLevel)))
5265         {
5266                 const int       width           = getLevel(baseLevel).getWidth();
5267                 const int       height          = getLevel(baseLevel).getHeight();
5268                 const bool      isMipmap        = isMipmapFilter(getSampler().minFilter);
5269                 const int       numLevels       = isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels2D(width, height)) : 1;
5270
5271                 m_levels.updateSamplerMode(mode);
5272                 m_view = tcu::TextureCubeArrayView(numLevels, m_levels.getEffectiveLevels() + baseLevel);
5273         }
5274         else
5275                 m_view = tcu::TextureCubeArrayView(0, DE_NULL);
5276 }
5277
5278 tcu::Vec4 TextureCubeArray::sample (float s, float t, float r, float q, float lod) const
5279 {
5280         return m_view.sample(getSampler(), s, t, r, q, lod);
5281 }
5282
5283 void TextureCubeArray::sample4 (tcu::Vec4 output[4], const tcu::Vec4 packetTexcoords[4], float lodBias) const
5284 {
5285         const float             cubeSide                = (float)m_view.getSize();
5286         const tcu::Vec3 cubeCoords[4]   =
5287         {
5288                 packetTexcoords[0].toWidth<3>(),
5289                 packetTexcoords[1].toWidth<3>(),
5290                 packetTexcoords[2].toWidth<3>(),
5291                 packetTexcoords[3].toWidth<3>()
5292         };
5293
5294         for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
5295         {
5296                 const tcu::CubeFace face                        = tcu::selectCubeFace(cubeCoords[fragNdx]);
5297                 const tcu::Vec2         faceCoords[4]   =
5298                 {
5299                         tcu::projectToFace(face, cubeCoords[0]),
5300                         tcu::projectToFace(face, cubeCoords[1]),
5301                         tcu::projectToFace(face, cubeCoords[2]),
5302                         tcu::projectToFace(face, cubeCoords[3]),
5303                 };
5304
5305                 const tcu::Vec2 dFdx0 = faceCoords[1] - faceCoords[0];
5306                 const tcu::Vec2 dFdx1 = faceCoords[3] - faceCoords[2];
5307                 const tcu::Vec2 dFdy0 = faceCoords[2] - faceCoords[0];
5308                 const tcu::Vec2 dFdy1 = faceCoords[3] - faceCoords[1];
5309
5310                 const tcu::Vec2& dFdx = (fragNdx & 2) ? dFdx1 : dFdx0;
5311                 const tcu::Vec2& dFdy = (fragNdx & 1) ? dFdy1 : dFdy0;
5312
5313                 const float mu = de::max(de::abs(dFdx.x()), de::abs(dFdy.x()));
5314                 const float mv = de::max(de::abs(dFdx.y()), de::abs(dFdy.y()));
5315                 const float p = de::max(mu * cubeSide, mv * cubeSide);
5316
5317                 const float     lod = deFloatLog2(p) + lodBias;
5318
5319                 output[fragNdx] = sample(packetTexcoords[fragNdx].x(), packetTexcoords[fragNdx].y(), packetTexcoords[fragNdx].z(), packetTexcoords[fragNdx].w(), lod);
5320         }
5321 }
5322
5323 Texture3D::Texture3D (deUint32 name)
5324         : Texture       (name, TYPE_3D)
5325         , m_view        (0, DE_NULL)
5326 {
5327 }
5328
5329 Texture3D::~Texture3D (void)
5330 {
5331 }
5332
5333 void Texture3D::allocLevel (int level, const tcu::TextureFormat& format, int width, int height, int depth)
5334 {
5335         m_levels.allocLevel(level, format, width, height, depth);
5336 }
5337
5338 bool Texture3D::isComplete (void) const
5339 {
5340         const int       baseLevel       = getBaseLevel();
5341
5342         if (hasLevel(baseLevel))
5343         {
5344                 const tcu::ConstPixelBufferAccess&      level0          = getLevel(baseLevel);
5345                 const bool                                                      mipmap          = isMipmapFilter(getSampler().minFilter);
5346
5347                 if (mipmap)
5348                 {
5349                         const TextureFormat&    format          = level0.getFormat();
5350                         const int                               w                       = level0.getWidth();
5351                         const int                               h                       = level0.getHeight();
5352                         const int                               d                       = level0.getDepth();
5353                         const int                               numLevels       = de::min(getMaxLevel()-baseLevel+1, getNumMipLevels3D(w, h, d));
5354
5355                         for (int levelNdx = 1; levelNdx < numLevels; levelNdx++)
5356                         {
5357                                 if (hasLevel(baseLevel+levelNdx))
5358                                 {
5359                                         const tcu::ConstPixelBufferAccess&      level           = getLevel(baseLevel+levelNdx);
5360                                         const int                                                       expectedW       = getMipLevelSize(w, levelNdx);
5361                                         const int                                                       expectedH       = getMipLevelSize(h, levelNdx);
5362                                         const int                                                       expectedD       = getMipLevelSize(d, levelNdx);
5363
5364                                         if (level.getWidth()    != expectedW    ||
5365                                                 level.getHeight()       != expectedH    ||
5366                                                 level.getDepth()        != expectedD    ||
5367                                                 level.getFormat()       != format)
5368                                                 return false;
5369                                 }
5370                                 else
5371                                         return false;
5372                         }
5373                 }
5374
5375                 return true;
5376         }
5377         else
5378                 return false;
5379 }
5380
5381 tcu::Vec4 Texture3D::sample (float s, float t, float r, float lod) const
5382 {
5383         return m_view.sample(getSampler(), s, t, r, lod);
5384 }
5385
5386 void Texture3D::sample4 (tcu::Vec4 output[4], const tcu::Vec3 packetTexcoords[4], float lodBias) const
5387 {
5388         const float texWidth  = (float)m_view.getWidth();
5389         const float texHeight = (float)m_view.getHeight();
5390         const float texDepth  = (float)m_view.getDepth();
5391
5392         const tcu::Vec3 dFdx0 = packetTexcoords[1] - packetTexcoords[0];
5393         const tcu::Vec3 dFdx1 = packetTexcoords[3] - packetTexcoords[2];
5394         const tcu::Vec3 dFdy0 = packetTexcoords[2] - packetTexcoords[0];
5395         const tcu::Vec3 dFdy1 = packetTexcoords[3] - packetTexcoords[1];
5396
5397         for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
5398         {
5399                 const tcu::Vec3& dFdx = (fragNdx & 2) ? dFdx1 : dFdx0;
5400                 const tcu::Vec3& dFdy = (fragNdx & 1) ? dFdy1 : dFdy0;
5401
5402                 const float mu = de::max(de::abs(dFdx.x()), de::abs(dFdy.x()));
5403                 const float mv = de::max(de::abs(dFdx.y()), de::abs(dFdy.y()));
5404                 const float mw = de::max(de::abs(dFdx.z()), de::abs(dFdy.z()));
5405                 const float p = de::max(de::max(mu * texWidth, mv * texHeight), mw * texDepth);
5406
5407                 const float     lod = deFloatLog2(p) + lodBias;
5408
5409                 output[fragNdx] = sample(packetTexcoords[fragNdx].x(), packetTexcoords[fragNdx].y(), packetTexcoords[fragNdx].z(), lod);
5410         }
5411 }
5412
5413 void Texture3D::updateView (tcu::Sampler::DepthStencilMode mode)
5414 {
5415         const int baseLevel     = getBaseLevel();
5416
5417         if (hasLevel(baseLevel) && !isEmpty(getLevel(baseLevel)))
5418         {
5419                 const int       width           = getLevel(baseLevel).getWidth();
5420                 const int       height          = getLevel(baseLevel).getHeight();
5421                 const int       depth           = getLevel(baseLevel).getDepth();
5422                 const bool      isMipmap        = isMipmapFilter(getSampler().minFilter);
5423                 const int       numLevels       = isMipmap ? de::min(getMaxLevel()-baseLevel+1, getNumMipLevels3D(width, height, depth)) : 1;
5424
5425                 m_levels.updateSamplerMode(mode);
5426                 m_view = tcu::Texture3DView(numLevels, m_levels.getEffectiveLevels() + baseLevel);
5427         }
5428         else
5429                 m_view = tcu::Texture3DView(0, DE_NULL);
5430 }
5431
5432 Renderbuffer::Renderbuffer (deUint32 name)
5433         : NamedObject           (name)
5434 {
5435 }
5436
5437 Renderbuffer::~Renderbuffer (void)
5438 {
5439 }
5440
5441 void Renderbuffer::setStorage (const TextureFormat& format, int width, int height)
5442 {
5443         m_data.setStorage(format, width, height);
5444 }
5445
5446 Framebuffer::Framebuffer (deUint32 name)
5447         : NamedObject(name)
5448 {
5449 }
5450
5451 Framebuffer::~Framebuffer (void)
5452 {
5453 }
5454
5455 VertexArray::VertexArray (deUint32 name, int maxVertexAttribs)
5456         : NamedObject                                   (name)
5457         , m_elementArrayBufferBinding   (DE_NULL)
5458         , m_arrays                                              (maxVertexAttribs)
5459 {
5460         for (int i = 0; i < maxVertexAttribs; ++i)
5461         {
5462                 m_arrays[i].enabled                     = false;
5463                 m_arrays[i].size                        = 4;
5464                 m_arrays[i].stride                      = 0;
5465                 m_arrays[i].type                        = GL_FLOAT;
5466                 m_arrays[i].normalized          = false;
5467                 m_arrays[i].integer                     = false;
5468                 m_arrays[i].divisor                     = 0;
5469                 m_arrays[i].bufferDeleted       = false;
5470                 m_arrays[i].bufferBinding       = DE_NULL;
5471                 m_arrays[i].pointer                     = DE_NULL;
5472         }
5473 }
5474
5475 ShaderProgramObjectContainer::ShaderProgramObjectContainer (deUint32 name, ShaderProgram* program)
5476         : NamedObject   (name)
5477         , m_program             (program)
5478         , m_deleteFlag  (false)
5479 {
5480 }
5481
5482 ShaderProgramObjectContainer::~ShaderProgramObjectContainer (void)
5483 {
5484 }
5485
5486 } // rc
5487 } // sglr