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