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